Remove Hcs.ClientNet
This commit is contained in:
@ -1,7 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api
|
||||
{
|
||||
public abstract class ApiBase(ClientBase client)
|
||||
{
|
||||
protected ClientBase client = client;
|
||||
}
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.Bills;
|
||||
using Hcs.ClientNet.Api.Request.Bills;
|
||||
using Hcs.Service.Async.Bills;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api
|
||||
{
|
||||
// http://open-gkh.ru/BillsServiceAsync/
|
||||
public class BillsApi(ClientBase client) : ApiBase(client)
|
||||
{
|
||||
/// <summary>
|
||||
/// Экспорт платежных документов
|
||||
/// </summary>
|
||||
/// <param name="paymentDocumentID">Идентификатор платежного документа</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Платежные документы</returns>
|
||||
public async Task<IEnumerable<exportPaymentDocumentResultType>> ExportPaymentDocumentDataByPaymentDocumentIDAsync(string paymentDocumentID, CancellationToken token = default)
|
||||
{
|
||||
var request = new ExportPaymentDocumentDataRequest(client);
|
||||
return await request.ExecuteByPaymentDocumentIDAsync(paymentDocumentID, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Экспорт платежных документов
|
||||
/// </summary>
|
||||
/// <param name="year">Год</param>
|
||||
/// <param name="month">Месяц</param>
|
||||
/// <param name="fiasHouseGuid">Глобальный уникальный идентификатор дома по ФИАС</param>
|
||||
/// <param name="accountNumber">Номер лицевого счета/иной идентификатор плательщика</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Платежные документы</returns>
|
||||
public async Task<IEnumerable<exportPaymentDocumentResultType>> ExportPaymentDocumentDataByAccountNumberAsync(short year, int month, string fiasHouseGuid, string accountNumber, CancellationToken token = default)
|
||||
{
|
||||
var request = new ExportPaymentDocumentDataRequest(client);
|
||||
return await request.ExecuteByAccountNumberAsync(year, month, fiasHouseGuid, accountNumber, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Экспорт платежных документов
|
||||
/// </summary>
|
||||
/// <param name="year">Год</param>
|
||||
/// <param name="month">Месяц</param>
|
||||
/// <param name="fiasHouseGuid">Глобальный уникальный идентификатор дома по ФИАС</param>
|
||||
/// <param name="paymentDocumentNumber">Номер платежного документа, по которому внесена плата,
|
||||
/// присвоенный такому документу исполнителем в целях осуществления расчетов по внесению платы</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Платежные документы</returns>
|
||||
public async Task<IEnumerable<exportPaymentDocumentResultType>> ExportPaymentDocumentDataByPaymentDocumentNumberAsync(short year, int month, string fiasHouseGuid, string paymentDocumentNumber, CancellationToken token = default)
|
||||
{
|
||||
var request = new ExportPaymentDocumentDataRequest(client);
|
||||
return await request.ExecuteByPaymentDocumentNumberAsync(year, month, fiasHouseGuid, paymentDocumentNumber, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Импорт сведений о платежных документах
|
||||
/// </summary>
|
||||
/// <param name="payload">Пейлоад сведений о платежных документах</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>true, если операция выполнена успешно, иначе - false</returns>
|
||||
public async Task<bool> ImportPaymentDocumentDataAsync(ImportPaymentDocumentDataPayload payload, CancellationToken token = default)
|
||||
{
|
||||
var request = new ImportPaymentDocumentDataRequest(client);
|
||||
return await request.ExecuteAsync(payload, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.DeviceMetering;
|
||||
using Hcs.ClientNet.Api.Request.DeviceMetering;
|
||||
using Hcs.Service.Async.DeviceMetering;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api
|
||||
{
|
||||
// http://open-gkh.ru/DeviceMeteringServiceAsync/
|
||||
public class DeviceMeteringApi(ClientBase client) : ApiBase(client)
|
||||
{
|
||||
/// <summary>
|
||||
/// Экспорт истории показаний и поверок приборов учета пользователя, установленных в указанном доме
|
||||
/// </summary>
|
||||
/// <param name="payload">Пейлоад выборки ПУ</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Лицевые счета</returns>
|
||||
public async Task<IEnumerable<exportMeteringDeviceHistoryResultType>> ExportMeteringDeviceHistoryAsync(ExportMeteringDeviceHistoryPayload payload, CancellationToken token = default)
|
||||
{
|
||||
var request = new ExportMeteringDeviceHistoryRequest(client);
|
||||
return await request.ExecuteAsync(payload, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Импорт показаний приборов учета
|
||||
/// </summary>
|
||||
/// <param name="values">Показания прибора учета</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>true, если операция выполнена успешно, иначе - false</returns>
|
||||
public async Task<bool> ImportMeteringDeviceValuesAsync(importMeteringDeviceValuesRequestMeteringDevicesValues values, CancellationToken token = default)
|
||||
{
|
||||
var request = new ImportMeteringDeviceValuesRequest(client);
|
||||
return await request.ExecuteAsync(values, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,169 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.HouseManagement;
|
||||
using Hcs.ClientNet.Api.Request.HouseManagement;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api
|
||||
{
|
||||
// http://open-gkh.ru/HouseManagementServiceAsync/
|
||||
public class HouseManagementApi(ClientBase client) : ApiBase(client)
|
||||
{
|
||||
/// <summary>
|
||||
/// Экспорт лицевых счетов
|
||||
/// </summary>
|
||||
/// <param name="fiasHouseGuid">Глобальный уникальный идентификатор дома по ФИАС</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Лицевые счета</returns>
|
||||
public async Task<IEnumerable<exportAccountResultType>> ExportAccountAsync(string fiasHouseGuid, CancellationToken token = default)
|
||||
{
|
||||
var request = new ExportAccountRequest(client);
|
||||
return await request.ExecuteAsync(fiasHouseGuid, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает информацию о доме
|
||||
/// </summary>
|
||||
/// <param name="fiasHouseGuid">Глобальный уникальный идентификатор дома по ФИАС</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Информация о доме</returns>
|
||||
public async Task<IEnumerable<exportHouseResultType>> ExportHouseAsync(string fiasHouseGuid, CancellationToken token = default)
|
||||
{
|
||||
var request = new ExportHouseRequest(client);
|
||||
return await request.ExecuteAsync(fiasHouseGuid, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает все договора ресурсоснабжения
|
||||
/// </summary>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Договора ресурсоснабжения</returns>
|
||||
public async Task<IEnumerable<exportSupplyResourceContractResultType>> ExportSupplyResourceContractDataAsync(CancellationToken token = default)
|
||||
{
|
||||
var request = new ExportSupplyResourceContractDataRequest(client);
|
||||
return await request.ExecuteAsync(token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает договор ресурсоснабжения по его идентификатору в ГИС ЖКХ
|
||||
/// </summary>
|
||||
/// <param name="contractRootGuid">Идентификатор договора ресурсоснабжения в ГИС ЖКХ</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Договор ресурсоснабжения</returns>
|
||||
public async Task<exportSupplyResourceContractResultType> ExportSupplyResourceContractDataAsync(Guid contractRootGuid, CancellationToken token = default)
|
||||
{
|
||||
var request = new ExportSupplyResourceContractDataRequest(client);
|
||||
return await request.ExecuteAsync(contractRootGuid, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает договор ресурсоснабжения по номеру договора в ГИС ЖКХ
|
||||
/// </summary>
|
||||
/// <param name="contractNumber">Номер договора ресурсоснабжения в ГИС ЖКХ</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Договор ресурсоснабжения</returns>
|
||||
public async Task<exportSupplyResourceContractResultType> ExportSupplyResourceContractDataAsync(string contractNumber, CancellationToken token = default)
|
||||
{
|
||||
var request = new ExportSupplyResourceContractDataRequest(client);
|
||||
return await request.ExecuteAsync(contractNumber, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает объекты жилищного фонда из договора ресурсоснабжения по его идентификатору
|
||||
/// </summary>
|
||||
/// <param name="contractRootGuid">Идентификатор договора ресурсоснабжения в ГИС ЖКХ</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Объекты жилищного фонда</returns>
|
||||
public async Task<IEnumerable<exportSupplyResourceContractObjectAddressResultType>> ExportSupplyResourceContractObjectAddressDataAsync(Guid contractRootGuid, CancellationToken token = default)
|
||||
{
|
||||
var request = new ExportSupplyResourceContractObjectAddressDataRequest(client);
|
||||
return await request.ExecuteAsync(contractRootGuid, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Импорт лицевого счета
|
||||
/// </summary>
|
||||
/// <param name="payload">Пейлоад лицевого счета</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>true, если операция выполнена успешно, иначе - false</returns>
|
||||
public async Task<bool> ImportAccountDataAsync(ImportAccountDataPayload payload, CancellationToken token = default)
|
||||
{
|
||||
var request = new ImportAccountDataRequest(client);
|
||||
return await request.ExecuteAsync(payload, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Импорт сведений о ДУ (создание ДУ)
|
||||
/// </summary>
|
||||
/// <param name="payload">Пейлоад ДУ</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Импортированный договор</returns>
|
||||
public async Task<importContractResultType> ImportContractDataAsync(ImportContractDataPayload payload, CancellationToken token = default)
|
||||
{
|
||||
var request = new ImportContractDataRequest(client);
|
||||
return await request.ExecuteAsync(payload, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Импорт данных дома
|
||||
/// </summary>
|
||||
/// <param name="payload">Пейлоад данных дома</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>true, если операция выполнена успешно, иначе - false</returns>
|
||||
public async Task<bool> ImportHouseUODataAsync(ImportLivingHouseUODataPayload payload, CancellationToken token = default)
|
||||
{
|
||||
var request = new ImportHouseUODataRequest(client);
|
||||
return await request.ExecuteAsync(payload, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Импорт прибора учета
|
||||
/// </summary>
|
||||
/// <param name="meteringDevice">Прибор учета</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>true, если операция выполнена успешно, иначе - false</returns>
|
||||
public async Task<bool> ImportMeteringDeviceDataAsync(MeteringDeviceFullInformationType meteringDevice, CancellationToken token = default)
|
||||
{
|
||||
var request = new ImportMeteringDeviceDataRequest(client);
|
||||
return await request.ExecuteAsync(meteringDevice, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Импорт новости для информирования граждан
|
||||
/// </summary>
|
||||
/// <param name="payload">Пейлоад новости</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>true, если операция выполнена успешно, иначе - false</returns>
|
||||
public async Task<bool> ImportNotificationDataAsync(ImportNotificationDataPayload payload, CancellationToken token = default)
|
||||
{
|
||||
var request = new ImportNotificationDataRequest(client);
|
||||
return await request.ExecuteAsync(payload, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Импорт договора ресурсоснабжения с РСО
|
||||
/// </summary>
|
||||
/// <param name="payload">Пейлоад договора ресурсоснабжения</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Импортированный договор</returns>
|
||||
public async Task<getStateResultImportResultCommonResultImportSupplyResourceContract> ImportSupplyResourceContractDataAsync(ImportSupplyResourceContractDataPayload payload, CancellationToken token = default)
|
||||
{
|
||||
var request = new ImportSupplyResourceContractDataRequest(client);
|
||||
return await request.ExecuteAsync(payload, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Импорт проекта договора ресурсоснабжения с РСО
|
||||
/// </summary>
|
||||
/// <param name="payload">Пейлоад проекта договора ресурсоснабжения</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Импортированный проект договора</returns>
|
||||
public async Task<getStateResultImportResultCommonResultImportSupplyResourceContractProject> ImportSupplyResourceContractProjectAsync(ImportSupplyResourceContractProjectPayload payload, CancellationToken token = default)
|
||||
{
|
||||
var request = new ImportSupplyResourceContractProjectRequest(client);
|
||||
return await request.ExecuteAsync(payload, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Api.Request.Nsi;
|
||||
using Hcs.Service.Async.Nsi;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api
|
||||
{
|
||||
// http://open-gkh.ru/NsiService/
|
||||
public class NsiApi(ClientBase client) : ApiBase(client)
|
||||
{
|
||||
/// <summary>
|
||||
/// Возвращает данные справочника поставщика информации
|
||||
/// </summary>
|
||||
/// <param name="registryNumber">Реестровый номер справочника</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Данные справочника</returns>
|
||||
public async Task<IEnumerable<NsiItemType>> ExportDataProviderNsiItemAsync(exportDataProviderNsiItemRequestRegistryNumber registryNumber, CancellationToken token = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new ExportDataProviderNsiItemRequest(client);
|
||||
return await request.ExecuteAsync(registryNumber, token);
|
||||
}
|
||||
catch (NoResultsRemoteException)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Api.Request.NsiCommon;
|
||||
using Hcs.Service.Async.NsiCommon;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api
|
||||
{
|
||||
// http://open-gkh.ru/NsiCommonService/
|
||||
public class NsiCommonApi(ClientBase client) : ApiBase(client)
|
||||
{
|
||||
/// <summary>
|
||||
/// Возвращает данные общесистемного справочника
|
||||
/// </summary>
|
||||
/// <param name="registryNumber">Реестровый номер справочника</param>
|
||||
/// <param name="listGroup">Группа справочников, где NSI - общесистемный, а NSIRAO - ОЖФ</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Данные общесистемного справочника</returns>
|
||||
public async Task<NsiItemType> ExportNsiItemAsync(int registryNumber, ListGroup listGroup, CancellationToken token = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new ExportNsiItemRequest(client);
|
||||
return await request.ExecuteAsync(registryNumber, listGroup, token);
|
||||
}
|
||||
catch (NoResultsRemoteException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает перечень общесистемных справочников с указанием даты последнего изменения каждого из них
|
||||
/// </summary>
|
||||
/// <param name="listGroup">Группа справочников, где NSI - общесистемный, а NSIRAO - ОЖФ</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Перечень общесистемных справочников</returns>
|
||||
public async Task<NsiListType> ExportNsiListAsync(ListGroup listGroup, CancellationToken token = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new ExportNsiListRequest(client);
|
||||
return await request.ExecuteAsync(listGroup, token);
|
||||
}
|
||||
catch (NoResultsRemoteException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Api.Request.OrgRegistryCommon;
|
||||
using Hcs.Service.Async.OrgRegistryCommon;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api
|
||||
{
|
||||
// http://open-gkh.ru/OrganizationsRegistryCommonAsyncService/
|
||||
public class OrgRegistryCommonApi(ClientBase client) : ApiBase(client)
|
||||
{
|
||||
/// <summary>
|
||||
/// Экспорт сведений о поставщиках информации ИС
|
||||
/// </summary>
|
||||
/// <param name="isActual">Выгрузить только активных поставщиков данных</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Сведения о поставщиках данных</returns>
|
||||
public async Task<IEnumerable<exportDataProviderResultType>> ExportDataProviderAsync(bool isActual, CancellationToken token = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new ExportDataProviderRequest(client);
|
||||
return await request.ExecuteAsync(isActual, token);
|
||||
}
|
||||
catch (NoResultsRemoteException)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Экспорт сведений из реестра организаций
|
||||
/// </summary>
|
||||
/// <param name="ogrn">ОГРН</param>
|
||||
/// <param name="kpp">КПП</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>Сведения из реестра организаций</returns>
|
||||
public async Task<IEnumerable<exportOrgRegistryResultType>> ExportOrgRegistryAsync(string ogrn, string kpp, CancellationToken token = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new ExportOrgRegistryRequest(client);
|
||||
return await request.ExecuteAsync(ogrn, kpp, token);
|
||||
}
|
||||
catch (NoResultsRemoteException)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,241 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Registry;
|
||||
using Hcs.ClientNet.Api.Type;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Payload.Bills
|
||||
{
|
||||
// http://open-gkh.ru/Bills/importPaymentDocumentRequest.html
|
||||
public class ImportPaymentDocumentDataPayload
|
||||
{
|
||||
// http://open-gkh.ru/Bills/importPaymentDocumentRequest/PaymentInformation.html
|
||||
public class PaymentInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// БИК банка получателя
|
||||
/// </summary>
|
||||
public string bankBIK;
|
||||
|
||||
/// <summary>
|
||||
/// Номер расчетного счета
|
||||
/// </summary>
|
||||
public string operatingAccountNumber;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Начисление по услуге
|
||||
/// </summary>
|
||||
// http://open-gkh.ru/Bills/PaymentDocumentType/ChargeInfo.html
|
||||
public interface IChargeInfo { }
|
||||
|
||||
/// <summary>
|
||||
/// Главная коммунальная услуга
|
||||
/// </summary>
|
||||
// http://open-gkh.ru/Bills/PDServiceChargeType/MunicipalService.html
|
||||
public class MunicipalService : IChargeInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Необязательное. Перерасчеты, корректировки, руб.
|
||||
/// </summary>
|
||||
public decimal? moneyRecalculation;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Льготы, субсидии, скидки, руб.
|
||||
/// </summary>
|
||||
public decimal? moneyDiscount;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Норматив потребления коммунальных ресурсов в целях использования и содержания
|
||||
/// общего имущества в многоквартирном доме.
|
||||
/// </summary>
|
||||
public decimal? houseOverallNeedsNorm;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Норматив потребления коммунальных услуг.
|
||||
/// </summary>
|
||||
public decimal? individualConsumptionNorm;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Текущие показания приборов учёта коммунальных ресурсов - индивидуальных
|
||||
/// (квартирных).
|
||||
/// </summary>
|
||||
public decimal? individualConsumptionCurrentValue;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Текущие показания приборов учёта коммунальных ресурсов - коллективных (общедомовых).
|
||||
/// </summary>
|
||||
public decimal? houseOverallNeedsCurrentValue;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Суммарный объём коммунальных ресурсов в многоквартирном доме - в помещениях дома.
|
||||
/// </summary>
|
||||
public decimal? houseTotalIndividualConsumption;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Суммарный объём коммунальных ресурсов в многоквартирном доме - в целях содержания
|
||||
/// общего имущества в многоквартирном доме.
|
||||
/// </summary>
|
||||
public decimal? houseTotalHouseOverallNeeds;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Способ определения объема коммунальных ресурсов при индивидуальном потреблении.
|
||||
/// </summary>
|
||||
public MunicipalServiceVolumeDeterminingMethod? individualConsumptionVolumeDeterminingMethod;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Объем/площадь/кол-во коммунальных ресурсов при индивидуальном потреблении.
|
||||
/// </summary>
|
||||
public decimal? individualConsumptionVolumeValue;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Способ определения объема коммунальных ресурсов при содержании общего имущества.
|
||||
/// </summary>
|
||||
public MunicipalServiceVolumeDeterminingMethod? overallConsumptionVolumeDeterminingMethod;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Объем/площадь/кол-во коммунальных ресурсов при содержании общего имущества.
|
||||
/// </summary>
|
||||
public decimal? overallConsumptionVolumeValue;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Размер повышающего коэффициента.
|
||||
/// </summary>
|
||||
public decimal? multiplyingFactorRatio;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Размер превышения платы, рассчитанной с применением повышающего коэффициента над
|
||||
/// размером платы, рассчитанной без учета повышающего коэффициента, руб.
|
||||
/// </summary>
|
||||
public decimal? amountOfExcessFees;
|
||||
|
||||
/// <summary>
|
||||
/// К оплате за индивидуальное потребление коммунальной услуги, руб.
|
||||
/// </summary>
|
||||
public decimal? municipalServiceIndividualConsumptionPayable;
|
||||
|
||||
/// <summary>
|
||||
/// К оплате за общедомовое потребление коммунальной услуги, руб.
|
||||
/// </summary>
|
||||
public decimal? municipalServiceCommunalConsumptionPayable;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Размер платы за коммунальные услуги, индивидуальное потребление.
|
||||
/// </summary>
|
||||
public decimal? amountOfPaymentMunicipalServiceIndividualConsumption;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Размер платы за коммунальные услуги, общедомовые нужды.
|
||||
/// </summary>
|
||||
public decimal? amountOfPaymentMunicipalServiceCommunalConsumption;
|
||||
|
||||
/// <summary>
|
||||
/// Код услуги из справочника "Вид коммунальной услуги" НСИ 3
|
||||
/// </summary>
|
||||
public RegistryElement serviceType;
|
||||
|
||||
/// <summary>
|
||||
/// Тариф/Размер платы на кв.м, руб./Размер взноса на кв.м, руб.
|
||||
/// </summary>
|
||||
public decimal rate;
|
||||
|
||||
/// <summary>
|
||||
/// К оплате за расчетный период, руб.
|
||||
/// </summary>
|
||||
public decimal totalPayable;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Начислено за расчетный период (без перерасчетов и льгот), руб.
|
||||
/// </summary>
|
||||
public decimal? accountingPeriodTotal;
|
||||
}
|
||||
|
||||
// http://open-gkh.ru/Bills/importPaymentDocumentRequest/PaymentDocument.html
|
||||
public class PaymentDocument
|
||||
{
|
||||
/// <summary>
|
||||
/// Платежный реквизит
|
||||
/// </summary>
|
||||
public PaymentInformation paymentInformation;
|
||||
|
||||
/// <summary>
|
||||
/// Идентификатор лицевого счета
|
||||
/// </summary>
|
||||
public string accountGuid;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Номер платежного документа, по которому внесена плата, присвоенный такому
|
||||
/// документу исполнителем в целях осуществления расчетов по внесению платы
|
||||
/// </summary>
|
||||
public string paymentDocumentNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Начисления по услугам
|
||||
/// </summary>
|
||||
public List<IChargeInfo> chargeInfo;
|
||||
|
||||
/// <summary>
|
||||
/// Если true, то выставлен на оплату, иначе - отозван
|
||||
/// </summary>
|
||||
public bool exposeNotWithdraw;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Задолженность за предыдущие периоды, руб.
|
||||
/// </summary>
|
||||
public decimal? debtPreviousPeriods;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Аванс на начало расчетного периода, руб.
|
||||
/// </summary>
|
||||
public decimal? advanceBllingPeriod;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Итого к оплате за расчетный период c учетом задолженности/переплаты, руб.
|
||||
/// (по всему платежному документу)
|
||||
/// </summary>
|
||||
public decimal? totalPayableByPDWithDebtAndAdvance;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Сумма к оплате за расчетный период, руб. (по всему платежному документу).
|
||||
/// </summary>
|
||||
public decimal? totalPayableByPD;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Оплачено денежных средств, руб.
|
||||
/// </summary>
|
||||
public decimal? paidCash;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Дата последней поступившей оплаты
|
||||
/// </summary>
|
||||
public DateTime? dateOfLastReceivedPayment;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Если true, то передаваемые данные платежных документов, следует считать верными,
|
||||
/// даже если они отличаются от автоматически рассчитанных системой значений. В том случае, если параметр
|
||||
/// не заполнен, то ГИС ЖХК будет проводить автоматическую проверку рассчитываемых сумм по ПД.
|
||||
/// </summary>
|
||||
public bool confirmAmountsCorrect;
|
||||
|
||||
/// <summary>
|
||||
/// Месяц расчетного периода платежного документа
|
||||
/// </summary>
|
||||
public int month;
|
||||
|
||||
/// <summary>
|
||||
/// Год расчетного периода платежного документа
|
||||
/// </summary>
|
||||
public short year;
|
||||
|
||||
/// <summary>
|
||||
/// Сведения о платежных реквизитах получателя платежа - бизнес-ключ поиска размещенных платежных
|
||||
/// реквизитов в ГИС ЖКХ
|
||||
/// </summary>
|
||||
public PaymentInformation[] paymentInformation;
|
||||
|
||||
/// <summary>
|
||||
/// Размещаемый платежный документ. Максимум 500.
|
||||
/// </summary>
|
||||
public PaymentDocument[] paymentDocument;
|
||||
}
|
||||
}
|
||||
@ -1,91 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Registry;
|
||||
using System;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Payload.DeviceMetering
|
||||
{
|
||||
// http://open-gkh.ru/DeviceMetering/exportMeteringDeviceHistoryRequest.html
|
||||
public class ExportMeteringDeviceHistoryPayload
|
||||
{
|
||||
/// <summary>
|
||||
/// Необязательное. Список из уникальных идентификаторов домов по ФИАС, в которых установлены ПУ
|
||||
/// пользователей. Если не указано, то будут экспортироваться данные по всем ПУ пользователей.
|
||||
/// </summary>
|
||||
public string[] fiasHouseGuid;
|
||||
|
||||
/// <summary>
|
||||
/// Выборочное. Выбор между <see cref="meteringDeviceType"/>, <see cref="municipalResource"/> и
|
||||
/// <see cref="meteringDeviceRootGUID"/>. Тип прибора учета (НСИ 27). Максимум 100 по выбранным.
|
||||
/// </summary>
|
||||
public RegistryElement[] meteringDeviceType;
|
||||
|
||||
/// <summary>
|
||||
/// Выборочное. Выбор между <see cref="meteringDeviceType"/>, <see cref="municipalResource"/> и
|
||||
/// <see cref="meteringDeviceRootGUID"/>. Вид коммунального ресурса (НСИ 2). Максимум 100 по выбранным.
|
||||
/// </summary>
|
||||
public RegistryElement[] municipalResource;
|
||||
|
||||
/// <summary>
|
||||
/// Выборочное. Выбор между <see cref="meteringDeviceType"/>, <see cref="municipalResource"/> и
|
||||
/// <see cref="meteringDeviceRootGUID"/>. Идентификатор ПУ. Максимум 100 по выбранным.
|
||||
/// </summary>
|
||||
public string[] meteringDeviceRootGUID;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Дата ввода в эксплуатацию "С".
|
||||
/// </summary>
|
||||
public DateTime? commissioningDateFrom;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Дата ввода в эксплуатацию "П".
|
||||
/// </summary>
|
||||
public DateTime? сommissioningDateTo;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Выгружать архивированные или нет.
|
||||
/// </summary>
|
||||
public bool? serchArchived;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Дата архивации "С".
|
||||
/// </summary>
|
||||
public DateTime? archiveDateFrom;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Дата архивации "По".
|
||||
/// </summary>
|
||||
public DateTime? archiveDateTo;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Дата начала периода, за который выгружаются показания и поверки ПУ (по дате
|
||||
/// снятия показаний). Период выгрузки показаний ПУ (определяемый элементами <see cref="inputDateFrom"/>
|
||||
/// и <see cref="inputDateTo"/>) не должен выходить за пределы двух последовательных календарных месяцев.
|
||||
/// </summary>
|
||||
public DateTime? inputDateFrom;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Дата окончания периода, за который выгружаются показания и поверки ПУ (по дате
|
||||
/// снятия показаний). Период выгрузки показаний ПУ (определяемый элементами <see cref="inputDateFrom"/>
|
||||
/// и <see cref="inputDateTo"/>) не должен выходить за пределы двух последовательных календарных месяцев.
|
||||
/// </summary>
|
||||
public DateTime? inputDateTo;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Если флаг сброшен или отсутствует, то показания, введенные в систему гражданином,
|
||||
/// включаются в выгрузку. Если флаг установлен, то такие показания в выгрузку не включаются.
|
||||
/// </summary>
|
||||
public bool? excludePersonAsDataSource;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Если флаг сброшен или отсутствует, то показания, введенные в систему текущей
|
||||
/// организацией, включаются в выгрузку. Если флаг установлен, то такие показания в выгрузку не включаются.
|
||||
/// </summary>
|
||||
public bool? excludeCurrentOrgAsDataSource;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Если флаг сброшен или отсутствует, то показания, введенные в систему организациями
|
||||
/// отличной от текущей, включаются в выгрузку. Если флаг установлен, то такие показания в выгрузку
|
||||
/// не включаются.
|
||||
/// </summary>
|
||||
public bool? excludeOtherOrgAsDataSource;
|
||||
}
|
||||
}
|
||||
@ -1,97 +0,0 @@
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Payload.HouseManagement
|
||||
{
|
||||
// http://open-gkh.ru/HouseManagement/importAccountRequest/Account.html
|
||||
public class ImportAccountDataPayload
|
||||
{
|
||||
/// <summary>
|
||||
/// Тип лицевого счета
|
||||
/// </summary>
|
||||
public enum AccountType
|
||||
{
|
||||
/// <summary>
|
||||
/// Лицевой счет для оплаты за жилое помещение и коммунальные услуги
|
||||
/// </summary>
|
||||
UO,
|
||||
|
||||
/// <summary>
|
||||
/// Лицевой счет для оплаты за коммунальные услуги
|
||||
/// </summary>
|
||||
RSO,
|
||||
|
||||
/// <summary>
|
||||
/// Лицевой счет для оплаты капитального ремонта
|
||||
/// </summary>
|
||||
CR,
|
||||
|
||||
/// <summary>
|
||||
/// Лицевой счет РКЦ
|
||||
/// </summary>
|
||||
RC,
|
||||
|
||||
/// <summary>
|
||||
/// Лицевой счет ОГВ/ОМС
|
||||
/// </summary>
|
||||
OGVorOMS,
|
||||
|
||||
/// <summary>
|
||||
/// Лицевой счет ТКО
|
||||
/// </summary>
|
||||
TKO
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Номер лицевого счета или иной идентификатор плательщика. Максимум 30 символов.
|
||||
/// </summary>
|
||||
public string accountNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Идентификатор ЛС в ГИС ЖКХ (при обновлении данных ЛС).
|
||||
/// </summary>
|
||||
public string accountGUID;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Конкретизация оснований ЛС (договоров ресурсоснабжения, договоров социального найма,
|
||||
/// договоров по обращению с ТКО).
|
||||
/// </summary>
|
||||
public AccountReasonsImportType accountReasons;
|
||||
|
||||
/// <summary>
|
||||
/// Тип лицевого счета
|
||||
/// </summary>
|
||||
public AccountType accountType;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Количество проживающих, не больше 9999.
|
||||
/// </summary>
|
||||
public uint? livingPersonsNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Общая площадь для ЛС. Не более 4 цифр после целой.
|
||||
/// </summary>
|
||||
public decimal? totalSquare;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Жилая площадь. Не более 4 цифр после целой.
|
||||
/// </summary>
|
||||
public decimal? residentialSquare;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Отапливаемая площадь. Не более 4 цифр после целой.
|
||||
/// </summary>
|
||||
public decimal? heatedArea;
|
||||
|
||||
// TODO: Добавить причину закрытия лицевого счета
|
||||
|
||||
/// <summary>
|
||||
/// Помещения
|
||||
/// </summary>
|
||||
public AccountTypeAccommodation[] accomodations;
|
||||
|
||||
/// <summary>
|
||||
/// Сведения о платильщике
|
||||
/// </summary>
|
||||
public AccountTypePayerInfo payerInfo;
|
||||
}
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Registry;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Payload.HouseManagement
|
||||
{
|
||||
public class ImportContractDataPayload
|
||||
{
|
||||
// TODO: LicenseRequest
|
||||
|
||||
/// <summary>
|
||||
/// Объекты управления
|
||||
/// </summary>
|
||||
public importContractRequestContractPlacingContractContractObject[] contractObjects;
|
||||
|
||||
/// <summary>
|
||||
/// Номер документа
|
||||
/// </summary>
|
||||
public string docNum;
|
||||
|
||||
/// <summary>
|
||||
/// Дата заключения
|
||||
/// </summary>
|
||||
public DateTime signingDate;
|
||||
|
||||
/// <summary>
|
||||
/// Дата вступления в силу
|
||||
/// </summary>
|
||||
public DateTime effectiveDate;
|
||||
|
||||
/// <summary>
|
||||
/// Планируемая дата окончания
|
||||
/// </summary>
|
||||
public DateTime planDateComptetion;
|
||||
|
||||
// TODO: Вторая сторона договора
|
||||
|
||||
// TODO: Protocol
|
||||
|
||||
/// <summary>
|
||||
/// Ссылка на НСИ "Основание заключения договора" (реестровый номер 58)
|
||||
/// </summary>
|
||||
public RegistryElement contractBase;
|
||||
|
||||
/// <summary>
|
||||
/// Сведения о сроках
|
||||
/// </summary>
|
||||
public DateDetailsType dateDetailsType;
|
||||
|
||||
/// <summary>
|
||||
/// Договор на управление и приложения
|
||||
/// </summary>
|
||||
public AttachmentType[] contractAttachment;
|
||||
|
||||
// TODO: AgreementAttachment
|
||||
|
||||
// TODO: SignedOwners
|
||||
|
||||
// TODO: CommissioningPermitAgreement
|
||||
|
||||
// TODO: Charter
|
||||
|
||||
// TODO: LocalGovernmentDecision
|
||||
|
||||
// TODO: RegistryDecisionID
|
||||
|
||||
// TODO: AutomaticRollOverOneYear
|
||||
}
|
||||
}
|
||||
@ -1,95 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Registry;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Payload.HouseManagement
|
||||
{
|
||||
// http://open-gkh.ru/HouseManagement/importHouseUORequest/LivingHouse/LivingHouseToCreate.html
|
||||
// http://open-gkh.ru/HouseManagement/HouseBasicUOType.html
|
||||
public class ImportLivingHouseUODataPayload
|
||||
{
|
||||
/// <summary>
|
||||
/// Глобальный уникальный идентификатор дома по ФИАС
|
||||
/// </summary>
|
||||
public Guid fiasHouseGuid;
|
||||
|
||||
/// <summary>
|
||||
/// Общая площадь здания
|
||||
/// </summary>
|
||||
public decimal totalSquare;
|
||||
|
||||
/// <summary>
|
||||
/// Состояние (НСИ 24)
|
||||
/// </summary>
|
||||
public RegistryElement state;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Стадия жизненного цикла (НСИ 338).
|
||||
/// </summary>
|
||||
public RegistryElement lifeCycleStage;
|
||||
|
||||
/// <summary>
|
||||
/// Год ввода в эксплуатацию. До 2215 включительно.
|
||||
/// </summary>
|
||||
public short usedYear;
|
||||
|
||||
/// <summary>
|
||||
/// Количество этажей. До 999 включительно.
|
||||
/// </summary>
|
||||
public int floorCount;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. ОКТМО (обязательное для всех территорий, за исключением города и космодрома
|
||||
/// "Байконур"). Значение из ФИАС при наличии.
|
||||
/// </summary>
|
||||
public OKTMORefType oktmo;
|
||||
|
||||
/// <summary>
|
||||
/// Часовая зона. Справочник 32.
|
||||
/// </summary>
|
||||
public RegistryElement olsonTZ;
|
||||
|
||||
/// <summary>
|
||||
/// Наличие у дома статуса объекта культурного наследия
|
||||
/// </summary>
|
||||
public bool culturalHeritage;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Данные ОЖФ
|
||||
/// </summary>
|
||||
public OGFData[] ogfData;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Дом находится в муниципальной собственности и в полном объеме используется
|
||||
/// в качестве общежития. Принимает только false.
|
||||
/// </summary>
|
||||
public bool isMunicipalProperty;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Дом находится в собственности субъекта Российской Федерации и в полном объеме
|
||||
/// используется в качестве общежития. Принимает только false.
|
||||
/// </summary>
|
||||
public bool isRegionProperty;
|
||||
|
||||
/// <summary>
|
||||
/// Кадастровый номер
|
||||
/// </summary>
|
||||
public string cadastralNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Условный номер. При указании в ГИС ЖКХ осуществляется привязка к ЕГРП (поиск в ЕГРП выполняется
|
||||
/// по условному номеру).
|
||||
/// </summary>
|
||||
public string conditionalNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Жилой дом блокированной застройки (если не указан - аналог false).
|
||||
/// </summary>
|
||||
public bool hasBlocks;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Несколько жилых домов с одинаковым адресом (если не указан - аналог false)
|
||||
/// </summary>
|
||||
public bool hasMultipleHousesWithSameAddress;
|
||||
}
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Payload.HouseManagement
|
||||
{
|
||||
// http://open-gkh.ru/HouseManagement/importNotificationRequest/notification/Create.html
|
||||
public class ImportNotificationDataPayload
|
||||
{
|
||||
/// <summary>
|
||||
/// Выборочное. Строковое представление темы, вместо ссылки на справочник. Максимальная длина
|
||||
/// текста равно 200 символам.
|
||||
/// </summary>
|
||||
public string topic;
|
||||
|
||||
/// <summary>
|
||||
/// Выборочное. Тема из справочника 364, заместо строкового представления темы.
|
||||
/// </summary>
|
||||
public nsiRef topicFromRegistry;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Показывает высокую важность новости.
|
||||
/// </summary>
|
||||
public bool isImportant;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Текст новости с максимальной длиной в 5000 символов.
|
||||
/// </summary>
|
||||
public string content;
|
||||
|
||||
/// <summary>
|
||||
/// Адресаты. Подходящие типы для значения:
|
||||
/// <see cref="string"/>, если это глобальный уникальный идентификатор дома по ФИАС,
|
||||
/// <see cref="importNotificationRequestNotificationCreateRoomOwners"/>,
|
||||
/// <see cref="RegOrgType"/> либо true, если все дома.
|
||||
/// </summary>
|
||||
public List<Tuple<ItemsChoiceType29, object>> destinations;
|
||||
|
||||
/// <summary>
|
||||
/// Выборочное. Если true, то новость всегда актуальна. Иначе период актуальности берется из
|
||||
/// <see cref="startDate"/> и <see cref="endDate"/>.
|
||||
/// </summary>
|
||||
public bool isNotLimit;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Период актуальности "С". Обязательно задается в случае <see cref="isNotLimit"/> = false.
|
||||
/// </summary>
|
||||
public DateTime? startDate;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Период актуальности "ДО". Обязательно задается в случае <see cref="isNotLimit"/> = false.
|
||||
/// </summary>
|
||||
public DateTime? endDate;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Документы новостей.
|
||||
/// </summary>
|
||||
public AttachmentType[] attachment;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Если true, то новость отправляется адресатам.
|
||||
/// </summary>
|
||||
public bool isShipOff;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Признак "Для публикации в мобильном приложении".
|
||||
/// </summary>
|
||||
public bool isForPublishToMobileApp;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Информация для новости, публикуемой в мобильном приложении.
|
||||
/// </summary>
|
||||
public importNotificationRequestNotificationCreateMobileAppData mobileAppData;
|
||||
}
|
||||
}
|
||||
@ -1,212 +0,0 @@
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Payload.HouseManagement
|
||||
{
|
||||
// http://open-gkh.ru/HouseManagement/SupplyResourceContractType.html
|
||||
public class ImportSupplyResourceContractDataPayload
|
||||
{
|
||||
/// <summary>
|
||||
/// Если договор не является публичным и/или присутствует заключенный на бумажном носителе
|
||||
/// (электронной форме) и/или не заключен в отношении нежилых помещений в многоквартирных домах,
|
||||
/// то равно true, иначе - false
|
||||
/// </summary>
|
||||
public bool isContract;
|
||||
|
||||
/// <summary>
|
||||
/// Номер договора
|
||||
/// </summary>
|
||||
public string contractNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Дата заключения
|
||||
/// </summary>
|
||||
public DateTime signingDate;
|
||||
|
||||
/// <summary>
|
||||
/// Дата вступления в силу
|
||||
/// </summary>
|
||||
public DateTime effectiveDate;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Договор заключен на неопределенный срок или нет.
|
||||
/// </summary>
|
||||
public bool indefiniteTerm;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Автоматически пролонгировать договор на один год при наступлении
|
||||
/// даты окончания действия или нет.
|
||||
/// </summary>
|
||||
public bool automaticRollOverOneYear;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Дата окончания действия. Обязательно для заполнения, если
|
||||
/// <see cref="automaticRollOverOneYear"/> = true.
|
||||
/// </summary>
|
||||
public DateTime? comptetionDate;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Период передачи текущих показаний по индивидуальным приборам учета. Обязателен для
|
||||
/// заполнения, если поле <see cref="volumeDepends"/> = true ИЛИ если поле
|
||||
/// <see cref="meteringDeviceInformation"/> = true.
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypePeriod period;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Показывает, разрешена ли гражданам передача текущих показаний по
|
||||
/// индивидуальным приборам учета в любой день месяца. Заполнение возможно только если: в настройках
|
||||
/// организации установлена настройка "Разрешить передачу гражданам показаний индивидуальных или общих
|
||||
/// (квартирных) приборов учета в любой день месяца" ИЛИ в настройках организации установлена настройка
|
||||
/// "Разрешить передачу гражданам показаний индивидуальных или общих (квартирных) приборов учета только
|
||||
/// в сроки, установленные в договоре, или в любой день месяца, если в договоре установлен признак
|
||||
/// "Разрешить передачу показаний приборов учета в любой день месяца" И заполнен <see cref="period"/>.
|
||||
/// </summary>
|
||||
public bool indicationsAnyDay;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Ссылка на НСИ "Основание заключения договора" (реестровый номер 58). Значения
|
||||
/// брать из <see cref="Registry.Registry58"/>.
|
||||
/// </summary>
|
||||
public nsiRef[] contractBase;
|
||||
|
||||
/// <summary>
|
||||
/// Вторая сторона договора. Подходящие типы:
|
||||
/// <see cref="SupplyResourceContractTypeApartmentBuildingOwner"/>,
|
||||
/// <see cref="SupplyResourceContractTypeApartmentBuildingRepresentativeOwner"/>,
|
||||
/// <see cref="SupplyResourceContractTypeApartmentBuildingSoleOwner"/>,
|
||||
/// <see cref="SupplyResourceContractTypeLivingHouseOwner"/>,
|
||||
/// <see cref="SupplyResourceContractTypeOrganization"/> либо true, если это договор оферты.
|
||||
/// </summary>
|
||||
public object counterparty;
|
||||
|
||||
/// <summary>
|
||||
/// Если в договоре в наличии плановый объем и режим подачи поставки ресурсов то true, иначе - false
|
||||
/// </summary>
|
||||
public bool isPlannedVolume;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Тип ведения планового объема и режима подачи: D - в разрезе договора,
|
||||
/// O - в разрезе объектов жилищного фонда. Заполняется при наличии в договоре планового объема и
|
||||
/// режима поставки ресурсов.
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypePlannedVolumeType? plannedVolumeType;
|
||||
|
||||
/// <summary>
|
||||
/// Предмет договора. Максимум 100 записей.
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypeContractSubject[] contractSubject;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Размещение информации о начислениях за коммунальные услуги осуществляет: R(SO)- РСО,
|
||||
/// P(roprietor) - исполнитель коммунальных услуг. Заполняется, если порядок размещения информации
|
||||
/// о начислениях за коммунальные услуги ведется в разрезе договора.
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypeCountingResource? countingResource;
|
||||
|
||||
/// <summary>
|
||||
/// Показатели качества коммунальных ресурсов и температурный график ведутся: D - в разрезе договора,
|
||||
/// O - в разрезе объектов жилищного фонда
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypeSpecifyingQualityIndicators specifyingQualityIndicators;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Признак "Отсутствие присоединения сетей объектов жилищного фонда к централизованной
|
||||
/// системе водоснабжения". Может быть указан, только если показатели качества коммунальных ресурсов
|
||||
/// ведутся в разрезе договора и предмет договора включает коммунальную услугу "Холодное водоснабжение"
|
||||
/// И/ИЛИ "Горячее водоснабжение".
|
||||
/// </summary>
|
||||
public bool noConnectionToWaterSupply;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Данные об объекте жилищного фонда. При импорте договора должен быть добавлен как минимум
|
||||
/// один адрес объекта жилищного фонда.
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypeObjectAddress[] objectAddress;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Показатель качества (содержащийся в справочнике показателей качества). Если
|
||||
/// показатели указываются в разрезе договора, то ссылка на ОЖФ не заполняется. Если показатели
|
||||
/// указываются в разрезе ОЖФ, то ссылка на ОЖФ обязательна.
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypeQuality[] quality;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Иной показатель качества коммунального ресурса (не содержащийся в справочнике
|
||||
/// показателей качества). Если показатели указываются в разрезе договора, то ссылка на ОЖФ
|
||||
/// не заполняется. Если показатели указываются в разрезе ОЖФ, то ссылка на ОЖФ обязательна.
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypeOtherQualityIndicator[] otherQualityIndicator;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Информация о температурном графике. Если показатели качества указываются в разрезе
|
||||
/// договора, то ссылка на ОЖФ в данном элементе не заполняется и элемент может заполняться только если
|
||||
/// в предмете договора хотя бы раз встречается ресурс "Тепловая энергия". Если показатели качества
|
||||
/// указываются в разрезе ОЖФ, то ссылка на ОЖФ обязательна и элемент заполняется только если
|
||||
/// в рамках ОЖФ встречается ресурс "Тепловая энергия".
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypeTemperatureChart[] temperatureChart;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Срок представления (выставления) платежных документов, не позднее. Является
|
||||
/// обязательным, если вторая сторона договора отличается от "Управляющая организация" ИЛИ если
|
||||
/// заполнено поле <see cref="meteringDeviceInformation"/>. Не заполняется, если
|
||||
/// <see cref="oneTimePayment"/> = true.
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypeBillingDate billingDate;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Срок внесения платы, не позднее. Является обязательным, если вторая сторона договора
|
||||
/// отличается от "Управляющая организация" И договор не является публичным и/или присутствует
|
||||
/// заключенный на бумажном носителе или в электронной форме И в поле
|
||||
/// <see cref="oneTimePayment"/> = false. Не заполняется, если <see cref="oneTimePayment"/> = true.
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypePaymentDate paymentDate;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Срок предоставления информации о поступивших платежах, не позднее. Является
|
||||
/// обязательным, если второй стороной договора является "Управляющая организация",
|
||||
/// "Размещение информации о начислениях за коммунальные услуги осуществляет" = "РСО" И
|
||||
/// договор не является публичным и/или присутствует заключенный на бумажном носителе или в
|
||||
/// электронной форме.
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypeProvidingInformationDate providingInformationDate;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Указывает на то, что размещение информации об индивидуальных приборах учета и их
|
||||
/// показаниях осуществляет ресурсоснабжающая организация или нет. Обязательно для заполнения,
|
||||
/// если в <see cref="countingResource"/> указано "РСО". В остальных случаях не заполняется.
|
||||
/// </summary>
|
||||
public bool? meteringDeviceInformation;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Указывает на то, что объем поставки ресурса(ов) определяется на основании прибора
|
||||
/// учета или нет. Поле не заполняется, если вторая сторона договора "Управляющая организация"
|
||||
/// ИЛИ поле <see cref="oneTimePayment"/> = true.
|
||||
/// </summary>
|
||||
public bool? volumeDepends;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Указывает на то, что оплата предоставленных услуг осуществляется ли единоразово
|
||||
/// при отгрузке указанных ресурсов без заведения лицевых счетов для потребителей. Доступно
|
||||
/// для заполнения, только если вторая сторона договора отлична от "Управляющая организация".
|
||||
/// </summary>
|
||||
public bool? oneTimePayment;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Порядок размещения информации о начислениях за коммунальные услуги ведется: D - в
|
||||
/// разрезе договора, O - в разрезе объектов жилищного фонда. Заполняется, если второй стороной договора
|
||||
/// является исполнитель коммунальных услуг.
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypeAccrualProcedure? accrualProcedure;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Информация о применяемом тарифе.
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypeTariff[] tariff;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Информация о нормативе потребления коммунальной услуги.
|
||||
/// </summary>
|
||||
public SupplyResourceContractTypeNorm[] norm;
|
||||
}
|
||||
}
|
||||
@ -1,214 +0,0 @@
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Payload.HouseManagement
|
||||
{
|
||||
// http://open-gkh.ru/HouseManagement/SupplyResourceContractType.html
|
||||
public class ImportSupplyResourceContractProjectPayload
|
||||
{
|
||||
/// <summary>
|
||||
/// Если договор не является публичным и/или присутствует заключенный на бумажном носителе
|
||||
/// (электронной форме) и/или не заключен в отношении нежилых помещений в многоквартирных домах,
|
||||
/// то равно true, иначе - false
|
||||
/// </summary>
|
||||
public bool isContract;
|
||||
|
||||
/// <summary>
|
||||
/// Номер договора
|
||||
/// </summary>
|
||||
public string contractNumber;
|
||||
|
||||
/// <summary>
|
||||
/// Дата заключения
|
||||
/// </summary>
|
||||
public DateTime signingDate;
|
||||
|
||||
/// <summary>
|
||||
/// Дата вступления в силу
|
||||
/// </summary>
|
||||
public DateTime effectiveDate;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Договор заключен на неопределенный срок или нет.
|
||||
/// </summary>
|
||||
public bool indefiniteTerm;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Автоматически пролонгировать договор на один год при наступлении
|
||||
/// даты окончания действия или нет.
|
||||
/// </summary>
|
||||
public bool automaticRollOverOneYear;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Дата окончания действия. Обязательно для заполнения, если
|
||||
/// <see cref="automaticRollOverOneYear"/> = true.
|
||||
/// </summary>
|
||||
public DateTime? comptetionDate;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Период передачи текущих показаний по индивидуальным приборам учета. Обязателен для
|
||||
/// заполнения, если поле <see cref="volumeDepends"/> = true ИЛИ если поле
|
||||
/// <see cref="meteringDeviceInformation"/> = true.
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypePeriod period;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Показывает, разрешена ли гражданам передача текущих показаний по
|
||||
/// индивидуальным приборам учета в любой день месяца. Заполнение возможно только если: в настройках
|
||||
/// организации установлена настройка "Разрешить передачу гражданам показаний индивидуальных или общих
|
||||
/// (квартирных) приборов учета в любой день месяца" ИЛИ в настройках организации установлена настройка
|
||||
/// "Разрешить передачу гражданам показаний индивидуальных или общих (квартирных) приборов учета только
|
||||
/// в сроки, установленные в договоре, или в любой день месяца, если в договоре установлен признак
|
||||
/// "Разрешить передачу показаний приборов учета в любой день месяца" И заполнен <see cref="period"/>.
|
||||
/// </summary>
|
||||
public bool indicationsAnyDay;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Ссылка на НСИ "Основание заключения договора" (реестровый номер 58). Значения
|
||||
/// брать из <see cref="Registry.Registry58"/>.
|
||||
/// </summary>
|
||||
public nsiRef[] contractBase;
|
||||
|
||||
/// <summary>
|
||||
/// Вторая сторона договора. Подходящие типы:
|
||||
/// <see cref="SupplyResourceContractProjectTypeApartmentBuildingOwner"/>,
|
||||
/// <see cref="SupplyResourceContractProjectTypeApartmentBuildingRepresentativeOwner"/>,
|
||||
/// <see cref="SupplyResourceContractProjectTypeApartmentBuildingSoleOwner"/>,
|
||||
/// <see cref="SupplyResourceContractProjectTypeLivingHouseOwner"/>,
|
||||
/// <see cref="SupplyResourceContractProjectTypeOrganization"/> либо true, если это договор оферты.
|
||||
/// </summary>
|
||||
public object counterparty;
|
||||
|
||||
/// <summary>
|
||||
/// Если в договоре в наличии плановый объем и режим подачи поставки ресурсов то true, иначе - false
|
||||
/// </summary>
|
||||
public bool isPlannedVolume;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Тип ведения планового объема и режима подачи: D - в разрезе договора,
|
||||
/// O - в разрезе объектов жилищного фонда. Заполняется при наличии в договоре планового объема и
|
||||
/// режима поставки ресурсов.
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypePlannedVolumeType? plannedVolumeType;
|
||||
|
||||
/// <summary>
|
||||
/// Предмет договора. Максимум 100 записей.
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypeContractSubject[] contractSubject;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Размещение информации о начислениях за коммунальные услуги осуществляет: R(SO)- РСО,
|
||||
/// P(roprietor) - исполнитель коммунальных услуг. Заполняется, если порядок размещения информации
|
||||
/// о начислениях за коммунальные услуги ведется в разрезе договора.
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypeCountingResource? countingResource;
|
||||
|
||||
/// <summary>
|
||||
/// Показатели качества коммунальных ресурсов и температурный график ведутся: D - в разрезе договора,
|
||||
/// O - в разрезе объектов жилищного фонда
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypeSpecifyingQualityIndicators specifyingQualityIndicators;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Признак "Отсутствие присоединения сетей объектов жилищного фонда к централизованной
|
||||
/// системе водоснабжения". Может быть указан, только если показатели качества коммунальных ресурсов
|
||||
/// ведутся в разрезе договора и предмет договора включает коммунальную услугу "Холодное водоснабжение"
|
||||
/// И/ИЛИ "Горячее водоснабжение".
|
||||
/// </summary>
|
||||
public bool noConnectionToWaterSupply;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Показатель качества (содержащийся в справочнике показателей качества). Обязательно
|
||||
/// для заполнения, если показатели качества указываются в разрезе договора. Для пары КУ и КР
|
||||
/// "Горячее водоснабжение" и "Питьевая вода" указываются актуальные показатели, определенные для КР
|
||||
/// "Горячая вода" в справочнике показателей качества коммунальных ресурсов. Для пары КУ и КР
|
||||
/// "Горячее водоснабжение" и "Тепловая энергия" информация о показателях качества не заполняется
|
||||
/// только в том случае, если для договора (если показатели ведутся в разрезе договора) или
|
||||
/// ОЖФ в договоре (если показатели ведутся в разрезе ОЖФ) также указана пара КУ и КР
|
||||
/// "Горячее водоснабжение" и "Питьевая вода".
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypeQuality[] quality;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Иной показатель качества коммунального ресурса (не содержащийся в справочнике
|
||||
/// показателей качества).
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypeOtherQualityIndicator[] otherQualityIndicator;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Информация о температурном графике. Доступно для заполнения только если в
|
||||
/// предмете договора хотя бы раз встречается ресурс "Тепловая энергия".
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypeTemperatureChart[] temperatureChart;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Срок представления (выставления) платежных документов, не позднее. Является
|
||||
/// обязательным, если вторая сторона договора отличается от "Управляющая организация" ИЛИ если
|
||||
/// заполнено поле <see cref="meteringDeviceInformation"/>. Не заполняется, если
|
||||
/// <see cref="oneTimePayment"/> = true.
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypeBillingDate billingDate;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Срок внесения платы, не позднее. Является обязательным, если вторая сторона договора
|
||||
/// отличается от "Управляющая организация" И договор не является публичным и/или присутствует
|
||||
/// заключенный на бумажном носителе или в электронной форме И в поле
|
||||
/// <see cref="oneTimePayment"/> = false. Не заполняется, если <see cref="oneTimePayment"/> = true.
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypePaymentDate paymentDate;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Срок предоставления информации о поступивших платежах, не позднее. Является
|
||||
/// обязательным, если второй стороной договора является "Управляющая организация",
|
||||
/// "Размещение информации о начислениях за коммунальные услуги осуществляет" = "РСО" И
|
||||
/// договор не является публичным и/или присутствует заключенный на бумажном носителе или в
|
||||
/// электронной форме.
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypeProvidingInformationDate providingInformationDate;
|
||||
|
||||
/// <summary>
|
||||
/// Условное. Указывает на то, что размещение информации об индивидуальных приборах учета и их
|
||||
/// показаниях осуществляет ресурсоснабжающая организация или нет. Обязательно для заполнения,
|
||||
/// если в <see cref="countingResource"/> указано "РСО". В остальных случаях не заполняется.
|
||||
/// </summary>
|
||||
public bool? meteringDeviceInformation;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Указывает на то, что объем поставки ресурса(ов) определяется на основании прибора
|
||||
/// учета или нет. Поле не заполняется, если вторая сторона договора "Управляющая организация"
|
||||
/// ИЛИ поле <see cref="oneTimePayment"/> = true.
|
||||
/// </summary>
|
||||
public bool? volumeDepends;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Указывает на то, что оплата предоставленных услуг осуществляется ли единоразово
|
||||
/// при отгрузке указанных ресурсов без заведения лицевых счетов для потребителей. Доступно
|
||||
/// для заполнения, только если вторая сторона договора отлична от "Управляющая организация".
|
||||
/// </summary>
|
||||
public bool? oneTimePayment;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Порядок размещения информации о начислениях за коммунальные услуги ведется: D - в
|
||||
/// разрезе договора, O - в разрезе объектов жилищного фонда. Заполняется, если второй стороной договора
|
||||
/// является исполнитель коммунальных услуг.
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypeAccrualProcedure? accrualProcedure;
|
||||
|
||||
/// <summary>
|
||||
/// Кода ФИАС региона РФ, в котором применяются тарифы и/или нормативы потребления КУ (у поставщика
|
||||
/// данных должна быть подтвержденная функция РСО в этом Субъекте РФ).
|
||||
/// </summary>
|
||||
public string regionCodeFias;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Информация о применяемом тарифе. Заполнется при указании <see cref="regionCodeFias"/>.
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypeRegionalSettingsTariff[] tariff;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Информация о нормативе потребления коммунальной услуги. Заполнется при
|
||||
/// указании <see cref="regionCodeFias"/>.
|
||||
/// </summary>
|
||||
public SupplyResourceContractProjectTypeRegionalSettingsNorm[] norm;
|
||||
}
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Payload.Payments
|
||||
{
|
||||
// http://open-gkh.ru/Payment/importNotificationsOfOrderExecutionRequest/NotificationOfOrderExecution139Type.html
|
||||
public class ImportNotificationsOfOrderExecutionPayload
|
||||
{
|
||||
/// <summary>
|
||||
/// Уникальный номер платежа (идентификатор операции)
|
||||
/// </summary>
|
||||
public string orderId;
|
||||
|
||||
/// <summary>
|
||||
/// Дата
|
||||
/// </summary>
|
||||
public DateTime orderDate;
|
||||
|
||||
/// <summary>
|
||||
/// Сумма оплаты (в копейках)
|
||||
/// </summary>
|
||||
public decimal amount;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Признак онлайн-оплаты.
|
||||
/// </summary>
|
||||
public bool? onlinePayment;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Год. Указывать совместно с <see cref="month"/>.
|
||||
/// </summary>
|
||||
public short? year;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Месяц. Указывать совместно с <see cref="year"/>.
|
||||
/// </summary>
|
||||
public int? month;
|
||||
|
||||
/// <summary>
|
||||
/// Идентификатор платежного документа
|
||||
/// </summary>
|
||||
public string paymentDocumentId;
|
||||
|
||||
/// <summary>
|
||||
/// GUID платежного документа
|
||||
/// </summary>
|
||||
public string paymentDocumentGUID;
|
||||
}
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Payload.Payments
|
||||
{
|
||||
// http://open-gkh.ru/Payment/importSupplierNotificationsOfOrderExecutionRequest/SupplierNotificationOfOrderExecution.html
|
||||
public class ImportSupplierNotificationsOfOrderExecutionPayload
|
||||
{
|
||||
/// <summary>
|
||||
/// Дата внесения платы (в случае отсутствия: дата поступления средств)
|
||||
/// </summary>
|
||||
public DateTime orderDate;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Месяц, за который вносится плата. Указывать совместно с <see cref="year"/>.
|
||||
/// </summary>
|
||||
public int? month;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Год, за который вносится плата. Указывать совместно с <see cref="month"/>.
|
||||
/// </summary>
|
||||
public short? year;
|
||||
|
||||
/// <summary>
|
||||
/// Идентификатор платежного документа
|
||||
/// </summary>
|
||||
public string paymentDocumentId;
|
||||
|
||||
/// <summary>
|
||||
/// Сумма
|
||||
/// </summary>
|
||||
public decimal amount;
|
||||
|
||||
/// <summary>
|
||||
/// Необязательное. Признак онлайн-оплаты.
|
||||
/// </summary>
|
||||
public bool? onlinePayment;
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.Payments;
|
||||
using Hcs.ClientNet.Api.Request.Payments;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api
|
||||
{
|
||||
// http://open-gkh.ru/PaymentsServiceAsync/
|
||||
public class PaymentsApi(ClientBase client) : ApiBase(client)
|
||||
{
|
||||
/// <summary>
|
||||
/// ВИ_ОПЛАТА_ИЗВ. Передать перечень документов "Извещение о принятии к исполнению распоряжения".
|
||||
/// </summary>
|
||||
/// <param name="payload">Пейлоад документа</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>true, если операция выполнена успешно, иначе - false</returns>
|
||||
public async Task<bool> ImportNotificationsOfOrderExecutionAsync(ImportNotificationsOfOrderExecutionPayload payload, CancellationToken token = default)
|
||||
{
|
||||
var request = new ImportNotificationsOfOrderExecutionRequest(client);
|
||||
return await request.ExecuteAsync(payload, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Импорт пакета документов "Извещение о принятии к исполнению распоряжения", размещаемых исполнителем
|
||||
/// </summary>
|
||||
/// <param name="payload">Пейлоад документа</param>
|
||||
/// <param name="token">Токен отмены</param>
|
||||
/// <returns>true, если операция выполнена успешно, иначе - false</returns>
|
||||
public async Task<bool> ImportSupplierNotificationsOfOrderExecutionAsync(ImportSupplierNotificationsOfOrderExecutionPayload payload, CancellationToken token = default)
|
||||
{
|
||||
var request = new ImportSupplierNotificationsOfOrderExecutionRequest(client);
|
||||
return await request.ExecuteAsync(payload, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Registry
|
||||
{
|
||||
/// <summary>
|
||||
/// НСИ "Межповерочный интервал" (реестровый номер 16).
|
||||
/// Взято из https://dom.gosuslugi.ru/opendataapi/nsi-16/v1.
|
||||
/// </summary>
|
||||
public static class Registry16
|
||||
{
|
||||
/// <summary>
|
||||
/// 4 года
|
||||
/// </summary>
|
||||
public static RegistryElement Element4 => new(
|
||||
"4",
|
||||
"e5e3288d-2994-41f7-8e44-f329b09ab77f");
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Registry
|
||||
{
|
||||
/// <summary>
|
||||
/// НСИ "Коммунальный ресурс" (реестровый номер 2).
|
||||
/// Взято из https://dom.gosuslugi.ru/opendataapi/nsi-2/v1.
|
||||
/// </summary>
|
||||
public static class Registry2
|
||||
{
|
||||
/// <summary>
|
||||
/// Тепловая энергия
|
||||
/// </summary>
|
||||
public static RegistryElement Element5 => new(
|
||||
"5",
|
||||
"44af905f-09c3-4cc3-b749-70048a53d8cf");
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Registry
|
||||
{
|
||||
/// <summary>
|
||||
/// НСИ "Тарифицируемый ресурс" (реестровый номер 239).
|
||||
/// Взято из https://dom.gosuslugi.ru/opendataapi/nsi-239/v1.
|
||||
/// </summary>
|
||||
public static class Registry239
|
||||
{
|
||||
/// <summary>
|
||||
/// Тепловая энергия
|
||||
/// </summary>
|
||||
public static RegistryElement Element4 => new(
|
||||
"4",
|
||||
"eec6e4b8-76c8-4fce-99b7-c95718edad19");
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Registry
|
||||
{
|
||||
/// <summary>
|
||||
/// НСИ "Состояние дома" (реестровый номер 24).
|
||||
/// Взято из https://dom.gosuslugi.ru/opendataapi/nsi-24/v1.
|
||||
/// </summary>
|
||||
public static class Registry24
|
||||
{
|
||||
/// <summary>
|
||||
/// Аварийный
|
||||
/// </summary>
|
||||
public static RegistryElement Element1 => new(
|
||||
"1",
|
||||
"cbe05853-a91b-43cc-a2cb-06cdfa97d492");
|
||||
|
||||
/// <summary>
|
||||
/// Исправный
|
||||
/// </summary>
|
||||
public static RegistryElement Element2 => new(
|
||||
"2",
|
||||
"2d3ae73e-6c72-4740-9122-9c632d1893a7");
|
||||
|
||||
/// <summary>
|
||||
/// Ветхий
|
||||
/// </summary>
|
||||
public static RegistryElement Element3 => new(
|
||||
"3",
|
||||
"bf083ae4-e4ec-4ace-b190-4d009e5cd1a1");
|
||||
|
||||
/// <summary>
|
||||
/// Не выбран
|
||||
/// </summary>
|
||||
public static RegistryElement Element4 => new(
|
||||
"4",
|
||||
"4ee07c0b-82d6-41f4-a8c5-2cff784bbd9c");
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Registry
|
||||
{
|
||||
/// <summary>
|
||||
/// НСИ "Тип прибора учета" (реестровый номер 27).
|
||||
/// Взято из https://dom.gosuslugi.ru/opendataapi/nsi-27/v1.
|
||||
/// </summary>
|
||||
public static class Registry27
|
||||
{
|
||||
/// <summary>
|
||||
/// Индивидуальный
|
||||
/// </summary>
|
||||
public static RegistryElement Element1 => new(
|
||||
"1",
|
||||
"3a9687b5-caed-4ec6-8a08-f4d3d012f2c7");
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Registry
|
||||
{
|
||||
/// <summary>
|
||||
/// НСИ "Показатели качества коммунальных ресурсов" (реестровый номер 276).
|
||||
/// Взято из https://dom.gosuslugi.ru/opendataapi/nsi-276/v1.
|
||||
/// </summary>
|
||||
public static class Registry276
|
||||
{
|
||||
/// <summary>
|
||||
/// Величина тепловой нагрузки
|
||||
/// </summary>
|
||||
public static RegistryElement Element4 => new(
|
||||
"4",
|
||||
"51dd6edc-83fe-4810-8b62-4dc85a75e9a3");
|
||||
|
||||
/// <summary>
|
||||
/// Диапазон давления теплоносителя в подающем трубопроводе
|
||||
/// </summary>
|
||||
public static RegistryElement Element10 => new(
|
||||
"10",
|
||||
"a5a17c90-cc4b-4f32-a22b-6e06cd42a68c");
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Registry
|
||||
{
|
||||
/// <summary>
|
||||
/// НСИ "Вид коммунальной услуги" (реестровый номер 3).
|
||||
/// Взято из https://dom.gosuslugi.ru/opendataapi/nsi-3/v1.
|
||||
/// </summary>
|
||||
public static class Registry3
|
||||
{
|
||||
/// <summary>
|
||||
/// Отопление
|
||||
/// </summary>
|
||||
public static RegistryElement Element6 => new(
|
||||
"6",
|
||||
"74925764-ddf3-4b4b-b18d-85994187c13a");
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Registry
|
||||
{
|
||||
/// <summary>
|
||||
/// НСИ "Часовые зоны по Olson" (реестровый номер 32).
|
||||
/// Взято из https://dom.gosuslugi.ru/opendataapi/nsi-32/v1.
|
||||
/// </summary>
|
||||
public static class Registry32
|
||||
{
|
||||
/// <summary>
|
||||
/// Иркутск
|
||||
/// </summary>
|
||||
public static RegistryElement Element11 => new(
|
||||
"11",
|
||||
"244ae392-0b96-46f2-80ea-4dac32e7326a");
|
||||
}
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Registry
|
||||
{
|
||||
/// <summary>
|
||||
/// НСИ "Стадия жизненного цикла" (реестровый номер 338).
|
||||
/// Взято из https://dom.gosuslugi.ru/opendataapi/nsi-338/v1.
|
||||
/// </summary>
|
||||
public static class Registry338
|
||||
{
|
||||
/// <summary>
|
||||
/// Эксплуатация
|
||||
/// </summary>
|
||||
public static RegistryElement Element1 => new(
|
||||
"1",
|
||||
"29b18683-5195-4ef4-83fc-71bf45597d46");
|
||||
|
||||
/// <summary>
|
||||
/// Реконструкция
|
||||
/// </summary>
|
||||
public static RegistryElement Element2 => new(
|
||||
"2",
|
||||
"75764145-f181-47e5-bff1-1306a46eb20e");
|
||||
|
||||
/// <summary>
|
||||
/// Капитальный ремонт с отселением
|
||||
/// </summary>
|
||||
public static RegistryElement Element3 => new(
|
||||
"3",
|
||||
"dee170df-db42-4cd6-9e5e-b62be91b3663");
|
||||
|
||||
/// <summary>
|
||||
/// Капитальный ремонт без отселения
|
||||
/// </summary>
|
||||
public static RegistryElement Element4 => new(
|
||||
"4",
|
||||
"91dc91e2-6883-4c84-b711-53f57f28dbe2");
|
||||
|
||||
/// <summary>
|
||||
/// Снос
|
||||
/// </summary>
|
||||
public static RegistryElement Element5 => new(
|
||||
"5",
|
||||
"cc358aa9-10b3-4d6a-bbec-c5f6b14950f6");
|
||||
|
||||
/// <summary>
|
||||
/// Не эксплуатируется, расселен
|
||||
/// </summary>
|
||||
public static RegistryElement Element6 => new(
|
||||
"6",
|
||||
"4bed3d7e-6015-428e-b4b4-7b7aec171c0d");
|
||||
|
||||
/// <summary>
|
||||
/// Выведен из эксплуатации
|
||||
/// </summary>
|
||||
public static RegistryElement Element7 => new(
|
||||
"7",
|
||||
"f3edc065-c1a1-4110-96fa-03313ae7a039");
|
||||
}
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Registry
|
||||
{
|
||||
/// <summary>
|
||||
/// НСИ "Вид коммунальной услуги" (реестровый номер 51)
|
||||
/// </summary>
|
||||
public static class Registry51
|
||||
{
|
||||
/// <summary>
|
||||
/// Отопление
|
||||
/// </summary>
|
||||
public static RegistryElement Element6_1 => new(
|
||||
"6.1",
|
||||
"14ad13a3-45ce-408b-b641-6fc59554f803");
|
||||
}
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Registry
|
||||
{
|
||||
/// <summary>
|
||||
/// НСИ "Основание заключения договора" (реестровый номер 58).
|
||||
/// Взято из https://dom.gosuslugi.ru/opendataapi/nsi-58/v1.
|
||||
/// </summary>
|
||||
public static class Registry58
|
||||
{
|
||||
/// <summary>
|
||||
/// Решение собрания собственников
|
||||
/// </summary>
|
||||
public static RegistryElement Element1 => new(
|
||||
"1",
|
||||
"110d48b2-32a9-4a44-939c-b784d9794621");
|
||||
|
||||
/// <summary>
|
||||
/// Открытый конкурс
|
||||
/// </summary>
|
||||
public static RegistryElement Element2 => new(
|
||||
"2",
|
||||
"a9dc59c3-d53f-42eb-ba98-cf8c74d88d36");
|
||||
|
||||
/// <summary>
|
||||
/// Договор управления
|
||||
/// </summary>
|
||||
public static RegistryElement Element3 => new(
|
||||
"3",
|
||||
"11efe618-79f8-4f53-bfd6-11620e8e9e1e");
|
||||
|
||||
/// <summary>
|
||||
/// Устав
|
||||
/// </summary>
|
||||
public static RegistryElement Element4 => new(
|
||||
"4",
|
||||
"a2eb920c-8163-4958-812a-ad153a5dfde6");
|
||||
|
||||
/// <summary>
|
||||
/// Решение правления
|
||||
/// </summary>
|
||||
public static RegistryElement Element5 => new(
|
||||
"5",
|
||||
"58639715-2708-4b8e-a5e6-7cae4ddbf03b");
|
||||
|
||||
/// <summary>
|
||||
/// Решение органа управления застройщика
|
||||
/// </summary>
|
||||
public static RegistryElement Element6 => new(
|
||||
"6",
|
||||
"9b606ef5-7701-4a12-a837-d81b50939160");
|
||||
|
||||
/// <summary>
|
||||
/// Заявление потребителя
|
||||
/// </summary>
|
||||
public static RegistryElement Element7 => new(
|
||||
"7",
|
||||
"93cd9d85-91b8-4bf9-ae48-c5f1e691949f");
|
||||
|
||||
/// <summary>
|
||||
/// Нормативный правовой акт
|
||||
/// </summary>
|
||||
public static RegistryElement Element8 => new(
|
||||
"8",
|
||||
"8b8ee37b-fa79-40cc-b98d-0e51f0c38d03");
|
||||
|
||||
/// <summary>
|
||||
/// Разрешение на ввод в эксплуатацию
|
||||
/// </summary>
|
||||
public static RegistryElement Element9 => new(
|
||||
"9",
|
||||
"16331000-d96e-4a33-a6c7-3cb9eacf4927");
|
||||
|
||||
/// <summary>
|
||||
/// Устав
|
||||
/// </summary>
|
||||
public static RegistryElement Element10 => new(
|
||||
"10",
|
||||
"555638ae-a207-46fa-99bd-88bdb297c45a");
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Registry
|
||||
{
|
||||
public class RegistryElement(string code, string guid)
|
||||
{
|
||||
public string Code { get; } = code;
|
||||
|
||||
public string GUID { get; } = guid;
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Request
|
||||
{
|
||||
public interface IAck
|
||||
{
|
||||
string MessageGUID { get; set; }
|
||||
|
||||
string RequesterMessageGUID { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.Adapter
|
||||
{
|
||||
public interface IAsyncClient<TRequestHeader> where TRequestHeader : class
|
||||
{
|
||||
Task<IGetStateResponse> GetStateAsync(TRequestHeader header, IGetStateRequest request);
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Request
|
||||
{
|
||||
public interface IErrorMessage
|
||||
{
|
||||
string ErrorCode { get; }
|
||||
|
||||
string Description { get; }
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Request
|
||||
{
|
||||
public interface IGetStateRequest
|
||||
{
|
||||
string MessageGUID { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Request.Adapter
|
||||
{
|
||||
public interface IGetStateResponse
|
||||
{
|
||||
IGetStateResult GetStateResult { get; }
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Request.Adapter
|
||||
{
|
||||
public interface IGetStateResult
|
||||
{
|
||||
sbyte RequestState { get; }
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Request.Adapter
|
||||
{
|
||||
public interface IGetStateResultMany : IGetStateResult
|
||||
{
|
||||
object[] Items { get; }
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Request.Adapter
|
||||
{
|
||||
public interface IGetStateResultOne : IGetStateResult
|
||||
{
|
||||
object Item { get; }
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Request
|
||||
{
|
||||
internal enum AsyncRequestStateType
|
||||
{
|
||||
Received = 1,
|
||||
InProgress,
|
||||
Ready
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request;
|
||||
using Hcs.ClientNet.Api.Request.Adapter;
|
||||
using Hcs.Service.Async.Bills;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.Service.Async.Bills
|
||||
{
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResult : IGetStateResultMany { }
|
||||
#pragma warning restore IDE1006
|
||||
|
||||
public partial class BillsPortsTypeAsyncClient : IAsyncClient<RequestHeader>
|
||||
{
|
||||
public async Task<IGetStateResponse> GetStateAsync(RequestHeader header, IGetStateRequest request)
|
||||
{
|
||||
return await getStateAsync(header, (getStateRequest)request);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResponse : IGetStateResponse
|
||||
#pragma warning restore IDE1006
|
||||
{
|
||||
public IGetStateResult GetStateResult => getStateResult;
|
||||
}
|
||||
|
||||
public partial class AckRequestAck : IAck { }
|
||||
|
||||
public partial class ErrorMessageType : IErrorMessage { }
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateRequest : IGetStateRequest { }
|
||||
#pragma warning restore IDE1006
|
||||
}
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.Bills
|
||||
{
|
||||
internal class BillsRequestBase(ClientBase client) :
|
||||
RequestBase<getStateResult,
|
||||
BillsPortsTypeAsyncClient,
|
||||
BillsPortsTypeAsync,
|
||||
RequestHeader,
|
||||
AckRequestAck,
|
||||
ErrorMessageType,
|
||||
getStateRequest>(client)
|
||||
{
|
||||
protected override EndPoint EndPoint => EndPoint.BillsAsync;
|
||||
|
||||
protected override bool EnableMinimalResponseWaitDelay => false;
|
||||
|
||||
protected override bool CanBeRestarted => false;
|
||||
|
||||
protected override int RestartTimeoutMinutes => 20;
|
||||
}
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.Bills;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.Bills
|
||||
{
|
||||
internal class ExportPaymentDocumentDataRequest(ClientBase client) : BillsRequestBase(client)
|
||||
{
|
||||
protected override bool CanBeRestarted => true;
|
||||
|
||||
internal async Task<IEnumerable<exportPaymentDocumentResultType>> ExecuteByPaymentDocumentIDAsync(string paymentDocumentID, CancellationToken token)
|
||||
{
|
||||
var request = new exportPaymentDocumentRequest()
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "13.1.0.1",
|
||||
Items = [paymentDocumentID],
|
||||
ItemsElementName = [ItemsChoiceType7.PaymentDocumentID]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.exportPaymentDocumentDataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
return result.Items.OfType<exportPaymentDocumentResultType>();
|
||||
}
|
||||
|
||||
internal async Task<IEnumerable<exportPaymentDocumentResultType>> ExecuteByAccountNumberAsync(short year, int month, string fiasHouseGuid, string accountNumber, CancellationToken token)
|
||||
{
|
||||
var request = new exportPaymentDocumentRequest()
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "13.1.0.1",
|
||||
Items = [year, month, fiasHouseGuid, accountNumber],
|
||||
ItemsElementName = [ItemsChoiceType7.Year, ItemsChoiceType7.Month, ItemsChoiceType7.FIASHouseGuid, ItemsChoiceType7.AccountNumber]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.exportPaymentDocumentDataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
return result.Items.OfType<exportPaymentDocumentResultType>();
|
||||
}
|
||||
|
||||
internal async Task<IEnumerable<exportPaymentDocumentResultType>> ExecuteByPaymentDocumentNumberAsync(short year, int month, string fiasHouseGuid, string paymentDocumentNumber, CancellationToken token)
|
||||
{
|
||||
var request = new exportPaymentDocumentRequest()
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "13.1.0.1",
|
||||
Items = [year, month, fiasHouseGuid, paymentDocumentNumber],
|
||||
ItemsElementName = [ItemsChoiceType7.Year, ItemsChoiceType7.Month, ItemsChoiceType7.FIASHouseGuid, ItemsChoiceType7.PaymentDocumentNumber]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.exportPaymentDocumentDataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
return result.Items.OfType<exportPaymentDocumentResultType>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,276 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.Bills;
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Api.Type;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.Bills;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.Bills
|
||||
{
|
||||
internal class ImportPaymentDocumentDataRequest(ClientBase client) : BillsRequestBase(client)
|
||||
{
|
||||
internal async Task<bool> ExecuteAsync(ImportPaymentDocumentDataPayload payload, CancellationToken token)
|
||||
{
|
||||
// TODO: Добавить проверку пейлоада
|
||||
|
||||
var request = GetRequestFromPayload(payload);
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.importPaymentDocumentDataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
result.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
|
||||
result.Items.OfType<CommonResultType>().ToList().ForEach(commonResult =>
|
||||
{
|
||||
commonResult.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private importPaymentDocumentRequest GetRequestFromPayload(ImportPaymentDocumentDataPayload payload)
|
||||
{
|
||||
var items = new List<object>();
|
||||
if (payload.confirmAmountsCorrect)
|
||||
{
|
||||
items.Add(true);
|
||||
}
|
||||
items.Add(payload.month);
|
||||
items.Add(payload.year);
|
||||
|
||||
var paymentInformations = new Dictionary<ImportPaymentDocumentDataPayload.PaymentInformation, importPaymentDocumentRequestPaymentInformation>();
|
||||
foreach (var entry in payload.paymentInformation)
|
||||
{
|
||||
var paymentInformation = new importPaymentDocumentRequestPaymentInformation()
|
||||
{
|
||||
TransportGUID = Guid.NewGuid().ToString(),
|
||||
BankBIK = entry.bankBIK,
|
||||
operatingAccountNumber = entry.operatingAccountNumber
|
||||
};
|
||||
paymentInformations.Add(entry, paymentInformation);
|
||||
|
||||
items.Add(paymentInformation);
|
||||
}
|
||||
|
||||
foreach (var entry in payload.paymentDocument)
|
||||
{
|
||||
var chargeInfo = new List<object>();
|
||||
foreach (var subEntry in entry.chargeInfo)
|
||||
{
|
||||
if (subEntry is ImportPaymentDocumentDataPayload.MunicipalService municipalService)
|
||||
{
|
||||
var item = new PDServiceChargeTypeMunicipalService()
|
||||
{
|
||||
ServiceType = new nsiRef()
|
||||
{
|
||||
Code = municipalService.serviceType.Code,
|
||||
GUID = municipalService.serviceType.GUID
|
||||
},
|
||||
Rate = municipalService.rate,
|
||||
TotalPayable = municipalService.totalPayable
|
||||
};
|
||||
|
||||
if (municipalService.moneyRecalculation.HasValue)
|
||||
{
|
||||
item.ServiceCharge = new ServiceChargeImportType()
|
||||
{
|
||||
MoneyRecalculation = municipalService.moneyRecalculation.Value,
|
||||
MoneyRecalculationSpecified = true
|
||||
};
|
||||
}
|
||||
if (municipalService.moneyDiscount.HasValue)
|
||||
{
|
||||
item.ServiceCharge ??= new ServiceChargeImportType();
|
||||
item.ServiceCharge.MoneyDiscount = municipalService.moneyDiscount.Value;
|
||||
item.ServiceCharge.MoneyDiscountSpecified = true;
|
||||
}
|
||||
|
||||
if (municipalService.houseOverallNeedsNorm.HasValue)
|
||||
{
|
||||
item.ServiceInformation = new ServiceInformation()
|
||||
{
|
||||
houseOverallNeedsNorm = municipalService.houseOverallNeedsNorm.Value,
|
||||
houseOverallNeedsNormSpecified = true
|
||||
};
|
||||
}
|
||||
if (municipalService.individualConsumptionNorm.HasValue)
|
||||
{
|
||||
item.ServiceInformation ??= new ServiceInformation();
|
||||
item.ServiceInformation.individualConsumptionNorm = municipalService.individualConsumptionNorm.Value;
|
||||
item.ServiceInformation.individualConsumptionNormSpecified = true;
|
||||
}
|
||||
if (municipalService.individualConsumptionCurrentValue.HasValue)
|
||||
{
|
||||
item.ServiceInformation ??= new ServiceInformation();
|
||||
item.ServiceInformation.individualConsumptionCurrentValue = municipalService.individualConsumptionCurrentValue.Value;
|
||||
item.ServiceInformation.individualConsumptionCurrentValueSpecified = true;
|
||||
}
|
||||
if (municipalService.houseOverallNeedsCurrentValue.HasValue)
|
||||
{
|
||||
item.ServiceInformation ??= new ServiceInformation();
|
||||
item.ServiceInformation.houseOverallNeedsCurrentValue = municipalService.houseOverallNeedsCurrentValue.Value;
|
||||
item.ServiceInformation.houseOverallNeedsCurrentValueSpecified = true;
|
||||
}
|
||||
if (municipalService.houseTotalIndividualConsumption.HasValue)
|
||||
{
|
||||
item.ServiceInformation ??= new ServiceInformation();
|
||||
item.ServiceInformation.houseTotalIndividualConsumption = municipalService.houseTotalIndividualConsumption.Value;
|
||||
item.ServiceInformation.houseTotalIndividualConsumptionSpecified = true;
|
||||
}
|
||||
if (municipalService.houseTotalHouseOverallNeeds.HasValue)
|
||||
{
|
||||
item.ServiceInformation ??= new ServiceInformation();
|
||||
item.ServiceInformation.houseTotalHouseOverallNeeds = municipalService.houseTotalHouseOverallNeeds.Value;
|
||||
item.ServiceInformation.houseTotalHouseOverallNeedsSpecified = true;
|
||||
}
|
||||
|
||||
var consumption = new List<PDServiceChargeTypeMunicipalServiceVolume>();
|
||||
if (municipalService.individualConsumptionVolumeDeterminingMethod.HasValue)
|
||||
{
|
||||
consumption.Add(new PDServiceChargeTypeMunicipalServiceVolume()
|
||||
{
|
||||
determiningMethod = municipalService.individualConsumptionVolumeDeterminingMethod.Value.ToServiceType(),
|
||||
determiningMethodSpecified = true,
|
||||
type = PDServiceChargeTypeMunicipalServiceVolumeType.I,
|
||||
typeSpecified = true,
|
||||
Value = municipalService.individualConsumptionVolumeValue.Value
|
||||
});
|
||||
}
|
||||
if (municipalService.overallConsumptionVolumeDeterminingMethod.HasValue)
|
||||
{
|
||||
consumption.Add(new PDServiceChargeTypeMunicipalServiceVolume()
|
||||
{
|
||||
determiningMethod = municipalService.overallConsumptionVolumeDeterminingMethod.Value.ToServiceType(),
|
||||
determiningMethodSpecified = true,
|
||||
type = PDServiceChargeTypeMunicipalServiceVolumeType.O,
|
||||
typeSpecified = true,
|
||||
Value = municipalService.overallConsumptionVolumeValue.Value
|
||||
});
|
||||
}
|
||||
item.Consumption = [.. consumption];
|
||||
|
||||
if (municipalService.multiplyingFactorRatio.HasValue)
|
||||
{
|
||||
item.MultiplyingFactor = new PDServiceChargeTypeMunicipalServiceMultiplyingFactor()
|
||||
{
|
||||
Ratio = municipalService.multiplyingFactorRatio.Value
|
||||
};
|
||||
|
||||
if (municipalService.amountOfExcessFees.HasValue)
|
||||
{
|
||||
item.MultiplyingFactor.AmountOfExcessFees = municipalService.amountOfExcessFees.Value;
|
||||
item.MultiplyingFactor.AmountOfExcessFeesSpecified = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (municipalService.municipalServiceIndividualConsumptionPayable.HasValue)
|
||||
{
|
||||
item.MunicipalServiceIndividualConsumptionPayable = municipalService.municipalServiceIndividualConsumptionPayable.Value;
|
||||
item.MunicipalServiceIndividualConsumptionPayableSpecified = true;
|
||||
}
|
||||
|
||||
if (municipalService.municipalServiceCommunalConsumptionPayable.HasValue)
|
||||
{
|
||||
item.MunicipalServiceCommunalConsumptionPayable = municipalService.municipalServiceCommunalConsumptionPayable.Value;
|
||||
item.MunicipalServiceCommunalConsumptionPayableSpecified = true;
|
||||
}
|
||||
|
||||
if (municipalService.amountOfPaymentMunicipalServiceIndividualConsumption.HasValue)
|
||||
{
|
||||
item.AmountOfPaymentMunicipalServiceIndividualConsumption = municipalService.amountOfPaymentMunicipalServiceIndividualConsumption.Value;
|
||||
item.AmountOfPaymentMunicipalServiceIndividualConsumptionSpecified = true;
|
||||
}
|
||||
|
||||
if (municipalService.amountOfPaymentMunicipalServiceCommunalConsumption.HasValue)
|
||||
{
|
||||
item.AmountOfPaymentMunicipalServiceCommunalConsumption = municipalService.amountOfPaymentMunicipalServiceCommunalConsumption.Value;
|
||||
item.AmountOfPaymentMunicipalServiceCommunalConsumptionSpecified = true;
|
||||
}
|
||||
|
||||
if (municipalService.accountingPeriodTotal.HasValue)
|
||||
{
|
||||
item.AccountingPeriodTotal = municipalService.accountingPeriodTotal.Value;
|
||||
item.AccountingPeriodTotalSpecified = true;
|
||||
}
|
||||
|
||||
chargeInfo.Add(new PaymentDocumentTypeChargeInfo()
|
||||
{
|
||||
Item = item
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: Обработать ошибку
|
||||
}
|
||||
|
||||
var paymentDocument = new importPaymentDocumentRequestPaymentDocument()
|
||||
{
|
||||
TransportGUID = Guid.NewGuid().ToString(),
|
||||
Items1 = [paymentInformations[entry.paymentInformation].TransportGUID],
|
||||
AccountGuid = entry.accountGuid,
|
||||
PaymentDocumentNumber = entry.paymentDocumentNumber,
|
||||
Items = [.. chargeInfo],
|
||||
Item = true,
|
||||
ItemElementName = entry.exposeNotWithdraw ? ItemChoiceType5.Expose : ItemChoiceType5.Withdraw
|
||||
};
|
||||
|
||||
if (entry.debtPreviousPeriods.HasValue)
|
||||
{
|
||||
paymentDocument.DebtPreviousPeriods = entry.debtPreviousPeriods.Value;
|
||||
paymentDocument.DebtPreviousPeriodsSpecified = true;
|
||||
}
|
||||
|
||||
if (entry.advanceBllingPeriod.HasValue)
|
||||
{
|
||||
paymentDocument.AdvanceBllingPeriod = entry.advanceBllingPeriod.Value;
|
||||
paymentDocument.AdvanceBllingPeriodSpecified = true;
|
||||
}
|
||||
|
||||
if (entry.totalPayableByPDWithDebtAndAdvance.HasValue)
|
||||
{
|
||||
paymentDocument.TotalPayableByPDWithDebtAndAdvance = entry.totalPayableByPDWithDebtAndAdvance.Value;
|
||||
paymentDocument.TotalPayableByPDWithDebtAndAdvanceSpecified = true;
|
||||
}
|
||||
|
||||
if (entry.totalPayableByPD.HasValue)
|
||||
{
|
||||
paymentDocument.TotalPayableByPD = entry.totalPayableByPD.Value;
|
||||
paymentDocument.TotalPayableByPDSpecified = true;
|
||||
}
|
||||
|
||||
if (entry.paidCash.HasValue)
|
||||
{
|
||||
paymentDocument.PaidCash = entry.paidCash.Value;
|
||||
paymentDocument.PaidCashSpecified = true;
|
||||
}
|
||||
|
||||
if (entry.dateOfLastReceivedPayment.HasValue)
|
||||
{
|
||||
paymentDocument.DateOfLastReceivedPayment = entry.dateOfLastReceivedPayment.Value;
|
||||
paymentDocument.DateOfLastReceivedPaymentSpecified = true;
|
||||
}
|
||||
|
||||
items.Add(paymentDocument);
|
||||
}
|
||||
|
||||
// http://open-gkh.ru/Bills/importPaymentDocumentRequest.html
|
||||
return new importPaymentDocumentRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "11.2.0.16",
|
||||
Items = [.. items]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request;
|
||||
using Hcs.ClientNet.Api.Request.Adapter;
|
||||
using Hcs.Service.Async.DeviceMetering;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.Service.Async.DeviceMetering
|
||||
{
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResult : IGetStateResultMany { }
|
||||
#pragma warning restore IDE1006
|
||||
|
||||
public partial class DeviceMeteringPortTypesAsyncClient : IAsyncClient<RequestHeader>
|
||||
{
|
||||
public async Task<IGetStateResponse> GetStateAsync(RequestHeader header, IGetStateRequest request)
|
||||
{
|
||||
return await getStateAsync(header, (getStateRequest)request);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResponse : IGetStateResponse
|
||||
#pragma warning restore IDE1006
|
||||
{
|
||||
public IGetStateResult GetStateResult => getStateResult;
|
||||
}
|
||||
|
||||
public partial class AckRequestAck : IAck { }
|
||||
|
||||
public partial class ErrorMessageType : IErrorMessage { }
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateRequest : IGetStateRequest { }
|
||||
#pragma warning restore IDE1006
|
||||
}
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.DeviceMetering
|
||||
{
|
||||
internal class DeviceMeteringRequestBase(ClientBase client) :
|
||||
RequestBase<getStateResult,
|
||||
DeviceMeteringPortTypesAsyncClient,
|
||||
DeviceMeteringPortTypesAsync,
|
||||
RequestHeader,
|
||||
AckRequestAck,
|
||||
ErrorMessageType,
|
||||
getStateRequest>(client)
|
||||
{
|
||||
protected override EndPoint EndPoint => EndPoint.DeviceMeteringAsync;
|
||||
|
||||
protected override bool EnableMinimalResponseWaitDelay => true;
|
||||
|
||||
protected override bool CanBeRestarted => true;
|
||||
|
||||
protected override int RestartTimeoutMinutes => 20;
|
||||
}
|
||||
}
|
||||
@ -1,179 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.DeviceMetering;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.DeviceMetering;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.DeviceMetering
|
||||
{
|
||||
internal class ExportMeteringDeviceHistoryRequest(ClientBase client) : DeviceMeteringRequestBase(client)
|
||||
{
|
||||
protected override bool EnableMinimalResponseWaitDelay => false;
|
||||
|
||||
internal async Task<IEnumerable<exportMeteringDeviceHistoryResultType>> 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<exportMeteringDeviceHistoryResultType>();
|
||||
}
|
||||
|
||||
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<object>();
|
||||
var itemsElementName = new List<ItemsChoiceType4>();
|
||||
if (payload.meteringDeviceType != null)
|
||||
{
|
||||
foreach (var meteringDeviceType in payload.meteringDeviceType)
|
||||
{
|
||||
items.Add(new nsiRef()
|
||||
{
|
||||
Code = meteringDeviceType.Code,
|
||||
GUID = meteringDeviceType.GUID
|
||||
});
|
||||
itemsElementName.Add(ItemsChoiceType4.MeteringDeviceType);
|
||||
}
|
||||
}
|
||||
if (payload.municipalResource != null)
|
||||
{
|
||||
foreach (var municipalResource in payload.municipalResource)
|
||||
{
|
||||
items.Add(new nsiRef()
|
||||
{
|
||||
Code = municipalResource.Code,
|
||||
GUID = municipalResource.GUID
|
||||
});
|
||||
itemsElementName.Add(ItemsChoiceType4.MunicipalResource);
|
||||
}
|
||||
}
|
||||
if (payload.meteringDeviceRootGUID != null)
|
||||
{
|
||||
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 = "13.1.3.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.DeviceMetering;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.DeviceMetering
|
||||
{
|
||||
internal class ImportMeteringDeviceValuesRequest(ClientBase client) : DeviceMeteringRequestBase(client)
|
||||
{
|
||||
protected override bool CanBeRestarted => false;
|
||||
|
||||
internal async Task<bool> ExecuteAsync(importMeteringDeviceValuesRequestMeteringDevicesValues values, CancellationToken token)
|
||||
{
|
||||
// http://open-gkh.ru/DeviceMetering/importMeteringDeviceValuesRequest.html
|
||||
var request = new importMeteringDeviceValuesRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "10.0.1.1",
|
||||
MeteringDevicesValues = [values]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.importMeteringDeviceValuesAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
result.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
|
||||
result.Items.OfType<CommonResultType>().ToList().ForEach(commonResult =>
|
||||
{
|
||||
commonResult.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Request
|
||||
{
|
||||
internal enum EndPoint
|
||||
{
|
||||
BillsAsync,
|
||||
DebtRequestsAsync,
|
||||
DeviceMeteringAsync,
|
||||
HomeManagementAsync,
|
||||
LicensesAsync,
|
||||
NsiAsync,
|
||||
NsiCommonAsync,
|
||||
OrgRegistryAsync,
|
||||
OrgRegistryCommonAsync,
|
||||
PaymentsAsync
|
||||
}
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request
|
||||
{
|
||||
internal class EndPointLocator
|
||||
{
|
||||
private static readonly Dictionary<EndPoint, string> endPoints;
|
||||
|
||||
static EndPointLocator()
|
||||
{
|
||||
endPoints ??= [];
|
||||
|
||||
endPoints.Add(EndPoint.BillsAsync, "ext-bus-bills-service/services/BillsAsync");
|
||||
endPoints.Add(EndPoint.DebtRequestsAsync, "ext-bus-debtreq-service/services/DebtRequestsAsync");
|
||||
endPoints.Add(EndPoint.DeviceMeteringAsync, "ext-bus-device-metering-service/services/DeviceMeteringAsync");
|
||||
endPoints.Add(EndPoint.HomeManagementAsync, "ext-bus-home-management-service/services/HomeManagementAsync");
|
||||
endPoints.Add(EndPoint.LicensesAsync, "ext-bus-licenses-service/services/LicensesAsync");
|
||||
endPoints.Add(EndPoint.NsiAsync, "ext-bus-nsi-service/services/NsiAsync");
|
||||
endPoints.Add(EndPoint.NsiCommonAsync, "ext-bus-nsi-common-service/services/NsiCommonAsync");
|
||||
endPoints.Add(EndPoint.OrgRegistryAsync, "ext-bus-org-registry-service/services/OrgRegistryAsync");
|
||||
endPoints.Add(EndPoint.OrgRegistryCommonAsync, "ext-bus-org-registry-common-service/services/OrgRegistryCommonAsync");
|
||||
endPoints.Add(EndPoint.PaymentsAsync, "ext-bus-payment-service/services/PaymentAsync");
|
||||
}
|
||||
|
||||
internal static string GetPath(EndPoint endPoint)
|
||||
{
|
||||
return endPoints[endPoint];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Request.Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Исключение указывает на то, что сервер обнаружил что у
|
||||
/// него нет объектов для выдачи по условию
|
||||
/// </summary>
|
||||
internal class NoResultsRemoteException : RemoteException
|
||||
{
|
||||
public NoResultsRemoteException(string description) : base(NO_OBJECTS_FOR_EXPORT, description) { }
|
||||
|
||||
public NoResultsRemoteException(string errorCode, string description) :
|
||||
base(errorCode, description) { }
|
||||
|
||||
public NoResultsRemoteException(string errorCode, string description, System.Exception nested) :
|
||||
base(errorCode, description, nested) { }
|
||||
}
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
using Hcs.ClientNet.Internal;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.Exception
|
||||
{
|
||||
internal class RemoteException : System.Exception
|
||||
{
|
||||
internal const string NO_OBJECTS_FOR_EXPORT = "INT002012";
|
||||
internal const string MISSING_IN_REGISTRY = "INT002000";
|
||||
internal const string ACCESS_DENIED = "AUT011003";
|
||||
|
||||
internal string ErrorCode { get; private set; }
|
||||
internal string Description { get; private set; }
|
||||
|
||||
public RemoteException(string errorCode, string description)
|
||||
: base(Combine(errorCode, description))
|
||||
{
|
||||
ErrorCode = errorCode;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
public RemoteException(string errorCode, string description, System.Exception nestedException)
|
||||
: base(Combine(errorCode, description), nestedException)
|
||||
{
|
||||
ErrorCode = errorCode;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
private static string Combine(string errorCode, string description)
|
||||
{
|
||||
return $"Remote server returned an error: [{errorCode}] {description}";
|
||||
}
|
||||
|
||||
internal static RemoteException CreateNew(string errorCode, string description, System.Exception nested = null)
|
||||
{
|
||||
if (string.Compare(errorCode, NO_OBJECTS_FOR_EXPORT) == 0)
|
||||
{
|
||||
return new NoResultsRemoteException(errorCode, description, nested);
|
||||
}
|
||||
return new RemoteException(errorCode, description);
|
||||
}
|
||||
|
||||
internal static RemoteException CreateNew(RemoteException nested)
|
||||
{
|
||||
if (nested == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(nested));
|
||||
}
|
||||
return CreateNew(nested.ErrorCode, nested.Description, nested);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает true, если ошибка @e или ее вложенные ошибки содержат @errorCode
|
||||
/// </summary>
|
||||
internal static bool ContainsErrorCode(SystemException e, string errorCode)
|
||||
{
|
||||
if (e == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Util.EnumerateInnerExceptions(e).OfType<RemoteException>().Where(x => x.ErrorCode == errorCode).Any();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
namespace Hcs.ClientNet.Api.Request.Exception
|
||||
{
|
||||
internal class RestartTimeoutException : System.Exception
|
||||
{
|
||||
public RestartTimeoutException(string message) : base(message) { }
|
||||
|
||||
public RestartTimeoutException(string message, System.Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request
|
||||
{
|
||||
internal class GostSigningEndpointBehavior(ClientBase client) : IEndpointBehavior
|
||||
{
|
||||
private readonly ClientBase client = client;
|
||||
|
||||
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
|
||||
|
||||
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
|
||||
{
|
||||
clientRuntime.ClientMessageInspectors.Add(
|
||||
new GostSigningMessageInspector(client));
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
|
||||
|
||||
public void Validate(ServiceEndpoint endpoint) { }
|
||||
}
|
||||
}
|
||||
@ -1,116 +0,0 @@
|
||||
using Hcs.ClientNet.Internal;
|
||||
using GostXades;
|
||||
using System.IO;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request
|
||||
{
|
||||
/// <summary>
|
||||
/// Фильтр сообщений добавляет в XML-сообщение электронную подпись XADES/GOST
|
||||
/// </summary>
|
||||
internal class GostSigningMessageInspector(ClientBase client) : IClientMessageInspector
|
||||
{
|
||||
private readonly ClientBase client = client;
|
||||
|
||||
public object BeforeSendRequest(ref Message request, IClientChannel channel)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filterHeader = "[Message Inspector]";
|
||||
|
||||
PurgeDebuggerHeaders(ref request);
|
||||
|
||||
var messageBody = GetMessageBodyString(ref request, Encoding.UTF8);
|
||||
if (!messageBody.Contains(Constants.SIGNED_XML_ELEMENT_ID))
|
||||
{
|
||||
client.TryCaptureMessage(true, messageBody);
|
||||
}
|
||||
else
|
||||
{
|
||||
var certInfo = X509Tools.GetFullnameWithExpirationDateStr(client.Certificate);
|
||||
client.TryLog($"{filterHeader} signing message with key [{certInfo}]...");
|
||||
|
||||
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
var service = new GostXadesBesService(client.CryptoProviderType);
|
||||
var signedXml = service.Sign(messageBody,
|
||||
Constants.SIGNED_XML_ELEMENT_ID,
|
||||
client.CertificateThumbprint,
|
||||
client.CertificatePassword);
|
||||
stopwatch.Stop();
|
||||
|
||||
client.TryLog($"{filterHeader} message signed in {stopwatch.ElapsedMilliseconds} ms");
|
||||
client.TryCaptureMessage(true, signedXml);
|
||||
|
||||
request = Message.CreateMessage(
|
||||
XmlReaderFromString(signedXml), int.MaxValue, request.Version);
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new System.Exception($"Exception occured in {GetType().Name}", ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void PurgeDebuggerHeaders(ref Message request)
|
||||
{
|
||||
var limit = request.Headers.Count;
|
||||
for (var i = 0; i < limit; ++i)
|
||||
{
|
||||
if (request.Headers[i].Name.Equals("VsDebuggerCausalityData"))
|
||||
{
|
||||
request.Headers.RemoveAt(i);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetMessageBodyString(ref Message request, Encoding encoding)
|
||||
{
|
||||
var mb = request.CreateBufferedCopy(int.MaxValue);
|
||||
request = mb.CreateMessage();
|
||||
|
||||
var s = new MemoryStream();
|
||||
var xw = XmlWriter.Create(s);
|
||||
mb.CreateMessage().WriteMessage(xw);
|
||||
xw.Flush();
|
||||
|
||||
s.Position = 0;
|
||||
|
||||
var bXML = new byte[s.Length];
|
||||
s.Read(bXML, 0, (int)s.Length);
|
||||
|
||||
if (bXML[0] != (byte)'<')
|
||||
{
|
||||
return encoding.GetString(bXML, 3, bXML.Length - 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
return encoding.GetString(bXML, 0, bXML.Length);
|
||||
}
|
||||
}
|
||||
|
||||
private XmlReader XmlReaderFromString(string xml)
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
var writer = new StreamWriter(stream);
|
||||
writer.Write(xml);
|
||||
writer.Flush();
|
||||
|
||||
stream.Position = 0;
|
||||
|
||||
return XmlReader.Create(stream);
|
||||
}
|
||||
|
||||
public void AfterReceiveReply(ref Message reply, object correlationState)
|
||||
{
|
||||
client.TryCaptureMessage(false, reply.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.HouseManagement
|
||||
{
|
||||
internal class ExportAccountRequest(ClientBase client) : HouseManagementRequestBase(client)
|
||||
{
|
||||
protected override bool EnableMinimalResponseWaitDelay => false;
|
||||
|
||||
internal async Task<IEnumerable<exportAccountResultType>> ExecuteAsync(string fiasHouseGuid, CancellationToken token)
|
||||
{
|
||||
// http://open-gkh.ru/HouseManagement/exportAccountRequest.html
|
||||
var request = new exportAccountRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "10.0.1.1",
|
||||
Items = [fiasHouseGuid],
|
||||
ItemsElementName = [ItemsChoiceType26.FIASHouseGuid]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.exportAccountDataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
return result.Items.OfType<exportAccountResultType>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.HouseManagement
|
||||
{
|
||||
internal class ExportHouseRequest(ClientBase client) : HouseManagementRequestBase(client)
|
||||
{
|
||||
protected override bool EnableMinimalResponseWaitDelay => false;
|
||||
|
||||
internal async Task<IEnumerable<exportHouseResultType>> ExecuteAsync(string fiasHouseGuid, CancellationToken token)
|
||||
{
|
||||
// http://open-gkh.ru/HouseManagement/exportHouseRequest.html
|
||||
var request = new exportHouseRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "15.6.0.1",
|
||||
FIASHouseGuid = fiasHouseGuid
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.exportHouseDataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
return result.Items.OfType<exportHouseResultType>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,135 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.HouseManagement
|
||||
{
|
||||
internal class ExportSupplyResourceContractDataRequest(ClientBase client) : HouseManagementRequestBase(client)
|
||||
{
|
||||
protected override bool EnableMinimalResponseWaitDelay => false;
|
||||
|
||||
internal async Task<IEnumerable<exportSupplyResourceContractResultType>> ExecuteAsync(CancellationToken token)
|
||||
{
|
||||
var result = new List<exportSupplyResourceContractResultType>();
|
||||
|
||||
void OnResultReceived(exportSupplyResourceContractResultType[] contracts)
|
||||
{
|
||||
if (contracts?.Length > 0)
|
||||
{
|
||||
result.AddRange(contracts);
|
||||
}
|
||||
}
|
||||
|
||||
var pageNum = 0;
|
||||
Guid? exportContractRootGuid = null;
|
||||
while (true)
|
||||
{
|
||||
pageNum++;
|
||||
|
||||
client.TryLog($"Querying page #{pageNum}...");
|
||||
|
||||
var data = await QueryBatchAsync(null, null, exportContractRootGuid, OnResultReceived, token);
|
||||
if (data.IsLastPage)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
exportContractRootGuid = data.NextGuid;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal async Task<exportSupplyResourceContractResultType> ExecuteAsync(Guid contractRootGuid, CancellationToken token)
|
||||
{
|
||||
exportSupplyResourceContractResultType result = null;
|
||||
|
||||
void OnResultReceived(exportSupplyResourceContractResultType[] contracts)
|
||||
{
|
||||
result = contracts?.Length > 0 ? contracts[0] : null;
|
||||
}
|
||||
|
||||
await QueryBatchAsync(contractRootGuid, null, null, OnResultReceived, token);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal async Task<exportSupplyResourceContractResultType> ExecuteAsync(string contractNumber, CancellationToken token)
|
||||
{
|
||||
exportSupplyResourceContractResultType result = null;
|
||||
|
||||
void OnResultReceived(exportSupplyResourceContractResultType[] contracts)
|
||||
{
|
||||
result = contracts?.Length > 0 ? contracts[0] : null;
|
||||
}
|
||||
|
||||
await QueryBatchAsync(null, contractNumber, null, OnResultReceived, token);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<PaginationData> QueryBatchAsync(
|
||||
Guid? contractRootGuid, string contractNumber, Guid? exportContractRootGuid,
|
||||
Action<exportSupplyResourceContractResultType[]> onResultReceived,
|
||||
CancellationToken token)
|
||||
{
|
||||
var itemsElementName = new List<ItemsChoiceType32>();
|
||||
var items = new List<object>();
|
||||
|
||||
if (contractRootGuid.HasValue)
|
||||
{
|
||||
itemsElementName.Add(ItemsChoiceType32.ContractRootGUID);
|
||||
items.Add(contractRootGuid.ToString());
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(contractNumber))
|
||||
{
|
||||
itemsElementName.Add(ItemsChoiceType32.ContractNumber);
|
||||
items.Add(contractNumber);
|
||||
}
|
||||
|
||||
if (exportContractRootGuid.HasValue)
|
||||
{
|
||||
itemsElementName.Add(ItemsChoiceType32.ExportContractRootGUID);
|
||||
items.Add(exportContractRootGuid.ToString());
|
||||
}
|
||||
|
||||
// http://open-gkh.ru/HouseManagement/exportSupplyResourceContractRequest.html
|
||||
var request = new exportSupplyResourceContractRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "13.1.1.1",
|
||||
ItemsElementName = [.. itemsElementName],
|
||||
Items = [.. items]
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var ackResponse = await asyncClient.exportSupplyResourceContractDataAsync(
|
||||
CreateRequestHeader(), request);
|
||||
return ackResponse.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
var contractResult = result.Items.OfType<getStateResultExportSupplyResourceContractResult>().First();
|
||||
onResultReceived?.Invoke(contractResult.Contract);
|
||||
|
||||
return new PaginationData(contractResult.Item);
|
||||
}
|
||||
catch (NoResultsRemoteException)
|
||||
{
|
||||
return PaginationData.CreateLastPageData();
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,96 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.HouseManagement
|
||||
{
|
||||
internal class ExportSupplyResourceContractObjectAddressDataRequest(ClientBase client) : HouseManagementRequestBase(client)
|
||||
{
|
||||
internal async Task<IEnumerable<exportSupplyResourceContractObjectAddressResultType>> ExecuteAsync(Guid contractRootGuid, CancellationToken token)
|
||||
{
|
||||
var result = new List<exportSupplyResourceContractObjectAddressResultType>();
|
||||
|
||||
void OnResultReceived(exportSupplyResourceContractObjectAddressResultType[] addresses)
|
||||
{
|
||||
if (addresses?.Length > 0)
|
||||
{
|
||||
result.AddRange(addresses);
|
||||
}
|
||||
}
|
||||
|
||||
var pageNum = 0;
|
||||
Guid? exportObjectGuid = null;
|
||||
while (true)
|
||||
{
|
||||
pageNum++;
|
||||
|
||||
client.TryLog($"Querying page #{pageNum}...");
|
||||
|
||||
var data = await QueryBatchAsync(contractRootGuid, exportObjectGuid, OnResultReceived, token);
|
||||
if (data.IsLastPage)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
exportObjectGuid = data.NextGuid;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<PaginationData> QueryBatchAsync(
|
||||
Guid contractRootGuid, Guid? exportObjectGuid,
|
||||
Action<exportSupplyResourceContractObjectAddressResultType[]> onResultReceived,
|
||||
CancellationToken token)
|
||||
{
|
||||
var itemsElementName = new List<ItemsChoiceType34>();
|
||||
var items = new List<string>();
|
||||
|
||||
itemsElementName.Add(ItemsChoiceType34.ContractRootGUID);
|
||||
items.Add(contractRootGuid.ToString());
|
||||
|
||||
if (exportObjectGuid.HasValue)
|
||||
{
|
||||
itemsElementName.Add(ItemsChoiceType34.ExportObjectGUID);
|
||||
items.Add(exportObjectGuid.ToString());
|
||||
}
|
||||
|
||||
// http://open-gkh.ru/HouseManagement/exportSupplyResourceContractObjectAddressRequest.html
|
||||
var request = new exportSupplyResourceContractObjectAddressRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "13.1.1.1",
|
||||
ItemsElementName = [.. itemsElementName],
|
||||
Items = [.. items]
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var ackResponse = await asyncClient.exportSupplyResourceContractObjectAddressDataAsync(
|
||||
CreateRequestHeader(), request);
|
||||
return ackResponse.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
var contractResult = result.Items.OfType<getStateResultExportSupplyResourceContractObjectAddress>().First();
|
||||
onResultReceived?.Invoke(contractResult.ObjectAddress);
|
||||
|
||||
return new PaginationData(contractResult.Item);
|
||||
}
|
||||
catch (NoResultsRemoteException)
|
||||
{
|
||||
return PaginationData.CreateLastPageData();
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,82 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request;
|
||||
using Hcs.ClientNet.Api.Request.Adapter;
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.Service.Async.HouseManagement
|
||||
{
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResult : IGetStateResultMany { }
|
||||
#pragma warning restore IDE1006
|
||||
|
||||
public partial class HouseManagementPortsTypeAsyncClient : IAsyncClient<RequestHeader>
|
||||
{
|
||||
public async Task<IGetStateResponse> GetStateAsync(RequestHeader header, IGetStateRequest request)
|
||||
{
|
||||
return await getStateAsync(header, (getStateRequest)request);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResponse : IGetStateResponse
|
||||
#pragma warning restore IDE1006
|
||||
{
|
||||
public IGetStateResult GetStateResult => getStateResult;
|
||||
}
|
||||
|
||||
public partial class AckRequestAck : IAck { }
|
||||
|
||||
public partial class ErrorMessageType : IErrorMessage { }
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateRequest : IGetStateRequest { }
|
||||
#pragma warning restore IDE1006
|
||||
}
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.HouseManagement
|
||||
{
|
||||
internal class HouseManagementRequestBase(ClientBase client) :
|
||||
RequestBase<getStateResult,
|
||||
HouseManagementPortsTypeAsyncClient,
|
||||
HouseManagementPortsTypeAsync,
|
||||
RequestHeader,
|
||||
AckRequestAck,
|
||||
ErrorMessageType,
|
||||
getStateRequest>(client)
|
||||
{
|
||||
protected override EndPoint EndPoint => EndPoint.HomeManagementAsync;
|
||||
|
||||
protected override bool EnableMinimalResponseWaitDelay => true;
|
||||
|
||||
protected override bool CanBeRestarted => true;
|
||||
|
||||
protected override int RestartTimeoutMinutes => 20;
|
||||
|
||||
protected getStateResultImportResultCommonResult[] GetCommonResults(IEnumerable<getStateResultImportResult> importResults)
|
||||
{
|
||||
var result = new List<getStateResultImportResultCommonResult>();
|
||||
foreach (var importResult in importResults)
|
||||
{
|
||||
importResult.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
|
||||
var commonResults = importResult.Items.OfType<getStateResultImportResultCommonResult>();
|
||||
foreach (var commonResult in commonResults)
|
||||
{
|
||||
commonResult.Items.OfType<CommonResultTypeError>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
}
|
||||
|
||||
result.AddRange(commonResults);
|
||||
}
|
||||
return [.. result];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,118 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.HouseManagement;
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.HouseManagement
|
||||
{
|
||||
internal class ImportAccountDataRequest(ClientBase client) : HouseManagementRequestBase(client)
|
||||
{
|
||||
protected override bool CanBeRestarted => false;
|
||||
|
||||
internal async Task<bool> ExecuteAsync(ImportAccountDataPayload payload, CancellationToken token)
|
||||
{
|
||||
// TODO: Добавить проверку пейлоада
|
||||
|
||||
// http://open-gkh.ru/HouseManagement/importAccountRequest.html
|
||||
var request = new importAccountRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "10.0.1.1",
|
||||
Account = [GetAccountFromPayload(payload)]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.importAccountDataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
result.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
|
||||
var importResults = result.Items.OfType<getStateResultImportResult>();
|
||||
var commonResults = GetCommonResults(importResults);
|
||||
foreach (var commonResult in commonResults)
|
||||
{
|
||||
if (commonResult.ItemElementName == ItemChoiceType26.ImportAccount)
|
||||
{
|
||||
return commonResult.Item is getStateResultImportResultCommonResultImportAccount;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private importAccountRequestAccount GetAccountFromPayload(ImportAccountDataPayload payload)
|
||||
{
|
||||
var account = new importAccountRequestAccount()
|
||||
{
|
||||
TransportGUID = Guid.NewGuid().ToString(),
|
||||
AccountNumber = payload.accountNumber,
|
||||
AccountGUID = payload.accountGUID,
|
||||
AccountReasons = payload.accountReasons,
|
||||
Item = true,
|
||||
Accommodation = payload.accomodations,
|
||||
PayerInfo = payload.payerInfo
|
||||
};
|
||||
|
||||
switch (payload.accountType)
|
||||
{
|
||||
case ImportAccountDataPayload.AccountType.UO:
|
||||
account.ItemElementName = ItemChoiceType8.isUOAccount;
|
||||
break;
|
||||
|
||||
case ImportAccountDataPayload.AccountType.RSO:
|
||||
account.ItemElementName = ItemChoiceType8.isRSOAccount;
|
||||
break;
|
||||
|
||||
case ImportAccountDataPayload.AccountType.CR:
|
||||
account.ItemElementName = ItemChoiceType8.isCRAccount;
|
||||
break;
|
||||
|
||||
case ImportAccountDataPayload.AccountType.RC:
|
||||
account.ItemElementName = ItemChoiceType8.isRCAccount;
|
||||
break;
|
||||
|
||||
case ImportAccountDataPayload.AccountType.OGVorOMS:
|
||||
account.ItemElementName = ItemChoiceType8.isOGVorOMSAccount;
|
||||
break;
|
||||
|
||||
case ImportAccountDataPayload.AccountType.TKO:
|
||||
account.ItemElementName = ItemChoiceType8.isTKOAccount;
|
||||
break;
|
||||
}
|
||||
|
||||
if (payload.livingPersonsNumber.HasValue)
|
||||
{
|
||||
account.LivingPersonsNumber = payload.livingPersonsNumber.Value.ToString();
|
||||
}
|
||||
|
||||
if (payload.totalSquare.HasValue)
|
||||
{
|
||||
account.TotalSquare = payload.totalSquare.Value;
|
||||
account.TotalSquareSpecified = true;
|
||||
}
|
||||
|
||||
if (payload.residentialSquare.HasValue)
|
||||
{
|
||||
account.ResidentialSquare = payload.residentialSquare.Value;
|
||||
account.ResidentialSquareSpecified = true;
|
||||
}
|
||||
|
||||
if (payload.heatedArea.HasValue)
|
||||
{
|
||||
account.HeatedArea = payload.heatedArea.Value;
|
||||
account.HeatedAreaSpecified = true;
|
||||
}
|
||||
|
||||
return account;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,85 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.HouseManagement;
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.HouseManagement
|
||||
{
|
||||
internal class ImportContractDataRequest(ClientBase client) : HouseManagementRequestBase(client)
|
||||
{
|
||||
protected override bool CanBeRestarted => false;
|
||||
internal async Task<importContractResultType> ExecuteAsync(ImportContractDataPayload payload, CancellationToken token)
|
||||
{
|
||||
// TODO: Добавить проверку пейлоада
|
||||
|
||||
// http://open-gkh.ru/HouseManagement/importContractRequest/Contract.html
|
||||
var contract = new importContractRequestContract
|
||||
{
|
||||
TransportGUID = Guid.NewGuid().ToString(),
|
||||
Item = GetContractFromPayload(payload)
|
||||
};
|
||||
|
||||
// http://open-gkh.ru/HouseManagement/importContractRequest.html
|
||||
var request = new importContractRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "11.9.0.1",
|
||||
Contract = [contract]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.importContractDataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
result.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
|
||||
var importResults = result.Items.OfType<getStateResultImportResult>();
|
||||
var commonResults = GetCommonResults(importResults);
|
||||
foreach (var commonResult in commonResults)
|
||||
{
|
||||
if (commonResult.ItemElementName == ItemChoiceType26.importContract)
|
||||
{
|
||||
if (commonResult.Item is importContractResultType importedContract)
|
||||
{
|
||||
return importedContract;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private importContractRequestContractPlacingContract GetContractFromPayload(ImportContractDataPayload payload)
|
||||
{
|
||||
// http://open-gkh.ru/HouseManagement/importContractRequest/Contract/PlacingContract.html
|
||||
var contract = new importContractRequestContractPlacingContract()
|
||||
{
|
||||
ContractObject = payload.contractObjects,
|
||||
DocNum = payload.docNum,
|
||||
SigningDate = payload.signingDate,
|
||||
EffectiveDate = payload.effectiveDate,
|
||||
PlanDateComptetion = payload.planDateComptetion,
|
||||
Item = true,
|
||||
ItemElementName = ItemChoiceType13.Owners,
|
||||
ContractBase = new nsiRef()
|
||||
{
|
||||
Code = payload.contractBase.Code,
|
||||
GUID = payload.contractBase.GUID
|
||||
},
|
||||
DateDetails = payload.dateDetailsType,
|
||||
ContractAttachment = payload.contractAttachment
|
||||
};
|
||||
|
||||
return contract;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,117 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.HouseManagement;
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.HouseManagement
|
||||
{
|
||||
internal class ImportHouseUODataRequest(ClientBase client) : HouseManagementRequestBase(client)
|
||||
{
|
||||
protected override bool CanBeRestarted => false;
|
||||
|
||||
internal async Task<bool> ExecuteAsync(ImportLivingHouseUODataPayload payload, CancellationToken token)
|
||||
{
|
||||
// TODO: Добавить проверку пейлоада
|
||||
|
||||
// http://open-gkh.ru/HouseManagement/importHouseUORequest.html
|
||||
var request = new importHouseUORequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "13.2.3.2",
|
||||
Item = GetLivingHouseFromPayload(payload)
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.importHouseUODataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
result.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
|
||||
var importResults = result.Items.OfType<getStateResultImportResult>();
|
||||
var commonResults = GetCommonResults(importResults);
|
||||
foreach (var commonResult in commonResults)
|
||||
{
|
||||
if (commonResult.ItemElementName == ItemChoiceType26.ImportHouseUO)
|
||||
{
|
||||
return commonResult.Item is OGFImportStatusType;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private importHouseUORequestLivingHouse GetLivingHouseFromPayload(ImportLivingHouseUODataPayload payload)
|
||||
{
|
||||
var livingHouse = new importHouseUORequestLivingHouseLivingHouseToCreate()
|
||||
{
|
||||
TransportGUID = Guid.NewGuid().ToString(),
|
||||
BasicCharacteristicts = new HouseBasicUOType()
|
||||
{
|
||||
FIASHouseGuid = payload.fiasHouseGuid.ToString(),
|
||||
TotalSquare = payload.totalSquare,
|
||||
State = new nsiRef()
|
||||
{
|
||||
Code = payload.state.Code,
|
||||
GUID = payload.state.GUID
|
||||
},
|
||||
LifeCycleStage = new nsiRef()
|
||||
{
|
||||
Code = payload.lifeCycleStage.Code,
|
||||
GUID = payload.lifeCycleStage.GUID
|
||||
},
|
||||
UsedYear = payload.usedYear,
|
||||
FloorCount = payload.floorCount,
|
||||
OKTMO = payload.oktmo,
|
||||
OlsonTZ = new nsiRef()
|
||||
{
|
||||
Code = payload.olsonTZ.Code,
|
||||
GUID = payload.olsonTZ.GUID
|
||||
},
|
||||
CulturalHeritage = payload.culturalHeritage,
|
||||
OGFData = payload.ogfData,
|
||||
// TODO: Разобраться с кадастровым номером
|
||||
Items = [true, payload.conditionalNumber],
|
||||
ItemsElementName = [ItemsChoiceType3.NoCadastralNumber, ItemsChoiceType3.ConditionalNumber]
|
||||
}
|
||||
};
|
||||
|
||||
if (!payload.isMunicipalProperty)
|
||||
{
|
||||
livingHouse.BasicCharacteristicts.IsMunicipalProperty = false;
|
||||
livingHouse.BasicCharacteristicts.IsMunicipalPropertySpecified = true;
|
||||
}
|
||||
|
||||
if (!payload.isRegionProperty)
|
||||
{
|
||||
livingHouse.BasicCharacteristicts.IsRegionProperty = false;
|
||||
livingHouse.BasicCharacteristicts.IsRegionPropertySpecified = true;
|
||||
}
|
||||
|
||||
if (payload.hasBlocks)
|
||||
{
|
||||
livingHouse.HasBlocks = true;
|
||||
livingHouse.HasBlocksSpecified = true;
|
||||
}
|
||||
|
||||
if (payload.hasMultipleHousesWithSameAddress)
|
||||
{
|
||||
livingHouse.HasMultipleHousesWithSameAddress = true;
|
||||
livingHouse.HasMultipleHousesWithSameAddressSpecified = true;
|
||||
}
|
||||
|
||||
return new importHouseUORequestLivingHouse()
|
||||
{
|
||||
Item = livingHouse
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.HouseManagement
|
||||
{
|
||||
internal class ImportMeteringDeviceDataRequest(ClientBase client) : HouseManagementRequestBase(client)
|
||||
{
|
||||
protected override bool CanBeRestarted => false;
|
||||
|
||||
internal async Task<bool> ExecuteAsync(MeteringDeviceFullInformationType meteringDevice, CancellationToken token)
|
||||
{
|
||||
// http://open-gkh.ru/HouseManagement/importMeteringDeviceDataRequest.html
|
||||
var request = new importMeteringDeviceDataRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "11.1.0.8",
|
||||
MeteringDevice =
|
||||
[
|
||||
new importMeteringDeviceDataRequestMeteringDevice()
|
||||
{
|
||||
TransportGUID = Guid.NewGuid().ToString(),
|
||||
Item = meteringDevice
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.importMeteringDeviceDataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
result.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
|
||||
var importResults = result.Items.OfType<getStateResultImportResult>();
|
||||
var commonResults = GetCommonResults(importResults);
|
||||
foreach (var commonResult in commonResults)
|
||||
{
|
||||
if (commonResult.ItemElementName == ItemChoiceType26.importMeteringDevice)
|
||||
{
|
||||
return commonResult.Item is getStateResultImportResultCommonResultImportMeteringDevice;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,113 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.HouseManagement;
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.HouseManagement
|
||||
{
|
||||
internal class ImportNotificationDataRequest(ClientBase client) : HouseManagementRequestBase(client)
|
||||
{
|
||||
protected override bool CanBeRestarted => false;
|
||||
|
||||
internal async Task<bool> ExecuteAsync(ImportNotificationDataPayload payload, CancellationToken token)
|
||||
{
|
||||
// TODO: Добавить проверку пейлоада
|
||||
|
||||
var notification = new importNotificationRequestNotification()
|
||||
{
|
||||
TransportGUID = Guid.NewGuid().ToString(),
|
||||
Item = GetNotificationFromPayload(payload)
|
||||
};
|
||||
|
||||
// http://open-gkh.ru/HouseManagement/importNotificationRequest.html
|
||||
var request = new importNotificationRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "13.2.2.0",
|
||||
notification = [notification]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.importNotificationDataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
result.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
|
||||
var importResults = result.Items.OfType<getStateResultImportResult>();
|
||||
var commonResults = GetCommonResults(importResults);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private importNotificationRequestNotificationCreate GetNotificationFromPayload(ImportNotificationDataPayload payload)
|
||||
{
|
||||
var notification = new importNotificationRequestNotificationCreate();
|
||||
|
||||
if (!string.IsNullOrEmpty(payload.topic))
|
||||
{
|
||||
notification.Item = payload.topic;
|
||||
}
|
||||
else
|
||||
{
|
||||
notification.Item = payload.topicFromRegistry;
|
||||
}
|
||||
|
||||
if (payload.isImportant)
|
||||
{
|
||||
notification.IsImportant = true;
|
||||
notification.IsImportantSpecified = true;
|
||||
}
|
||||
|
||||
notification.content = payload.content;
|
||||
|
||||
var items = new List<object>();
|
||||
var itemsElementName = new List<ItemsChoiceType29>();
|
||||
foreach (var tuple in payload.destinations)
|
||||
{
|
||||
items.Add(tuple.Item2);
|
||||
itemsElementName.Add(tuple.Item1);
|
||||
}
|
||||
notification.Items = [.. items];
|
||||
notification.ItemsElementName = [.. itemsElementName];
|
||||
|
||||
if (payload.isNotLimit)
|
||||
{
|
||||
notification.Items1 = [true];
|
||||
notification.Items1ElementName = [Items1ChoiceType.IsNotLimit];
|
||||
}
|
||||
else
|
||||
{
|
||||
notification.Items1 = [payload.startDate.Value, payload.endDate.Value];
|
||||
notification.Items1ElementName = [Items1ChoiceType.StartDate, Items1ChoiceType.EndDate];
|
||||
}
|
||||
|
||||
// TODO: Добавить добавление аттачмента
|
||||
|
||||
if (payload.isShipOff)
|
||||
{
|
||||
notification.IsShipOff = true;
|
||||
notification.IsShipOffSpecified = true;
|
||||
}
|
||||
|
||||
if (payload.isForPublishToMobileApp)
|
||||
{
|
||||
notification.IsForPublishToMobileApp = true;
|
||||
notification.IsForPublishToMobileAppSpecified = true;
|
||||
}
|
||||
|
||||
notification.MobileAppData = payload.mobileAppData;
|
||||
|
||||
return notification;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,302 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.HouseManagement;
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.HouseManagement
|
||||
{
|
||||
internal class ImportSupplyResourceContractDataRequest(ClientBase client) : HouseManagementRequestBase(client)
|
||||
{
|
||||
protected override bool CanBeRestarted => false;
|
||||
|
||||
internal async Task<getStateResultImportResultCommonResultImportSupplyResourceContract> ExecuteAsync(ImportSupplyResourceContractDataPayload payload, CancellationToken token)
|
||||
{
|
||||
ThrowIfPayloadIncorrect(payload);
|
||||
|
||||
// http://open-gkh.ru/HouseManagement/SupplyResourceContractType.html
|
||||
var contract = new importSupplyResourceContractRequestContract
|
||||
{
|
||||
TransportGUID = Guid.NewGuid().ToString(),
|
||||
Item1 = GetContractFromPayload(payload)
|
||||
};
|
||||
|
||||
// http://open-gkh.ru/HouseManagement/importSupplyResourceContractRequest.html
|
||||
var request = new importSupplyResourceContractRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "11.3.0.5",
|
||||
Contract = [contract]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.importSupplyResourceContractDataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
result.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
|
||||
var importResults = result.Items.OfType<getStateResultImportResult>();
|
||||
var commonResults = GetCommonResults(importResults);
|
||||
foreach (var commonResult in commonResults)
|
||||
{
|
||||
if (commonResult.ItemElementName == ItemChoiceType26.ImportSupplyResourceContract)
|
||||
{
|
||||
if (commonResult.Item is getStateResultImportResultCommonResultImportSupplyResourceContract importedContract)
|
||||
{
|
||||
return importedContract;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ThrowIfPayloadIncorrect(ImportSupplyResourceContractDataPayload payload)
|
||||
{
|
||||
if (string.IsNullOrEmpty(payload.contractNumber))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.contractNumber)} is empty");
|
||||
}
|
||||
|
||||
if (payload.signingDate.Equals(default) || payload.effectiveDate.Equals(default))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.signingDate)} OR/AND {nameof(payload.effectiveDate)} are default");
|
||||
}
|
||||
|
||||
if (!payload.comptetionDate.HasValue && payload.automaticRollOverOneYear)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.comptetionDate)} is null but {nameof(payload.automaticRollOverOneYear)} has value");
|
||||
}
|
||||
|
||||
if (payload.period == null && (payload.volumeDepends.HasValue && payload.volumeDepends.Value
|
||||
|| payload.meteringDeviceInformation.HasValue && payload.meteringDeviceInformation.Value))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.period)} is null but {nameof(payload.volumeDepends)} OR/AND {nameof(payload.meteringDeviceInformation)} have value");
|
||||
}
|
||||
|
||||
if (payload.indicationsAnyDay && payload.period == null)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.indicationsAnyDay)} has value but {nameof(payload.period)} is null");
|
||||
}
|
||||
|
||||
// TODO: Add counterparty check
|
||||
|
||||
if (payload.plannedVolumeType.HasValue && !payload.isPlannedVolume)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.plannedVolumeType)} has value but {nameof(payload.isPlannedVolume)} is false");
|
||||
}
|
||||
|
||||
if (payload.contractSubject == null || payload.contractSubject.Length == 0)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.contractSubject)} is empty");
|
||||
}
|
||||
|
||||
if (payload.contractSubject != null && payload.contractSubject.Length > 100)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.contractSubject)} exceeds its limit ({payload.contractSubject.Length} of 100)");
|
||||
}
|
||||
|
||||
if (payload.countingResource.HasValue && (!payload.accrualProcedure.HasValue ||
|
||||
payload.accrualProcedure.Value == SupplyResourceContractTypeAccrualProcedure.O))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.countingResource)} has value but {nameof(payload.accrualProcedure)} is null OR has inappropriate value");
|
||||
}
|
||||
|
||||
// TODO: Add noConnectionToWaterSupply check
|
||||
|
||||
if (payload.objectAddress == null || payload.objectAddress.Length == 0)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.objectAddress)} is empty");
|
||||
}
|
||||
|
||||
// TODO: Add quality check
|
||||
// TODO: Add otherQualityIndicator check
|
||||
// TODO: Add temperatureChart check
|
||||
|
||||
if (payload.billingDate == null && (payload.counterparty is not SupplyResourceContractTypeOrganization ||
|
||||
payload.meteringDeviceInformation.HasValue))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.billingDate)} is null but {nameof(payload.meteringDeviceInformation)} has value");
|
||||
}
|
||||
|
||||
if (payload.billingDate != null && payload.oneTimePayment.HasValue && payload.oneTimePayment.Value)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.billingDate)} has value but {nameof(payload.oneTimePayment)} is true");
|
||||
}
|
||||
|
||||
if (payload.paymentDate == null && payload.counterparty is not SupplyResourceContractTypeOrganization &&
|
||||
payload.isContract && payload.oneTimePayment.HasValue && !payload.oneTimePayment.Value)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.paymentDate)} is null but should have value");
|
||||
}
|
||||
|
||||
if (payload.paymentDate != null && payload.oneTimePayment.HasValue && payload.oneTimePayment.Value)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.paymentDate)} has value but {nameof(payload.oneTimePayment)} is true");
|
||||
}
|
||||
|
||||
if (payload.providingInformationDate == null && payload.counterparty is SupplyResourceContractTypeOrganization &&
|
||||
payload.countingResource.HasValue && payload.countingResource.Value == SupplyResourceContractTypeCountingResource.R &&
|
||||
payload.isContract)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.providingInformationDate)} is null but should have value");
|
||||
}
|
||||
|
||||
if (!payload.meteringDeviceInformation.HasValue &&
|
||||
payload.countingResource.HasValue && payload.countingResource == SupplyResourceContractTypeCountingResource.R)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.meteringDeviceInformation)} is null but should have value");
|
||||
}
|
||||
|
||||
if (payload.volumeDepends.HasValue && (payload.counterparty is SupplyResourceContractTypeOrganization ||
|
||||
payload.oneTimePayment.HasValue && payload.oneTimePayment.Value))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.volumeDepends)} has value but should have not one");
|
||||
}
|
||||
|
||||
if (payload.oneTimePayment.HasValue && payload.counterparty is SupplyResourceContractTypeOrganization)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.oneTimePayment)} has value but {nameof(payload.counterparty)} has inappropriate value");
|
||||
}
|
||||
|
||||
// TODO: Add accrualProcedure check
|
||||
}
|
||||
|
||||
private SupplyResourceContractType GetContractFromPayload(ImportSupplyResourceContractDataPayload payload)
|
||||
{
|
||||
// http://open-gkh.ru/HouseManagement/SupplyResourceContractType.html
|
||||
var contract = new SupplyResourceContractType();
|
||||
|
||||
if (payload.isContract)
|
||||
{
|
||||
var isContract = new SupplyResourceContractTypeIsContract()
|
||||
{
|
||||
ContractNumber = payload.contractNumber,
|
||||
SigningDate = payload.signingDate,
|
||||
EffectiveDate = payload.effectiveDate
|
||||
};
|
||||
contract.Item = isContract;
|
||||
}
|
||||
else
|
||||
{
|
||||
var isNotContract = new SupplyResourceContractTypeIsNotContract()
|
||||
{
|
||||
ContractNumber = payload.contractNumber,
|
||||
SigningDate = payload.signingDate,
|
||||
SigningDateSpecified = true,
|
||||
EffectiveDate = payload.effectiveDate,
|
||||
EffectiveDateSpecified = true
|
||||
};
|
||||
contract.Item = isNotContract;
|
||||
}
|
||||
|
||||
var items = new List<object>();
|
||||
var itemsElementName = new List<ItemsChoiceType9>();
|
||||
if (payload.indefiniteTerm)
|
||||
{
|
||||
items.Add(payload.indefiniteTerm);
|
||||
itemsElementName.Add(ItemsChoiceType9.IndefiniteTerm);
|
||||
}
|
||||
if (payload.automaticRollOverOneYear)
|
||||
{
|
||||
items.Add(payload.automaticRollOverOneYear);
|
||||
itemsElementName.Add(ItemsChoiceType9.AutomaticRollOverOneYear);
|
||||
|
||||
items.Add(payload.comptetionDate.Value);
|
||||
itemsElementName.Add(ItemsChoiceType9.ComptetionDate);
|
||||
}
|
||||
if (items.Count > 0 && itemsElementName.Count > 0)
|
||||
{
|
||||
contract.Items = [.. items];
|
||||
contract.ItemsElementName = [.. itemsElementName];
|
||||
}
|
||||
|
||||
if (payload.period != null)
|
||||
{
|
||||
contract.Period = payload.period;
|
||||
}
|
||||
|
||||
if (payload.indicationsAnyDay)
|
||||
{
|
||||
contract.IndicationsAnyDay = true;
|
||||
contract.IndicationsAnyDaySpecified = true;
|
||||
}
|
||||
|
||||
if (payload.contractBase != null && payload.contractBase.Length > 0)
|
||||
{
|
||||
contract.ContractBase = payload.contractBase;
|
||||
}
|
||||
|
||||
contract.Item1 = payload.counterparty;
|
||||
contract.IsPlannedVolume = payload.isPlannedVolume;
|
||||
|
||||
if (payload.plannedVolumeType.HasValue)
|
||||
{
|
||||
contract.PlannedVolumeType = payload.plannedVolumeType.Value;
|
||||
contract.PlannedVolumeTypeSpecified = true;
|
||||
}
|
||||
|
||||
contract.ContractSubject = payload.contractSubject;
|
||||
|
||||
if (payload.countingResource.HasValue)
|
||||
{
|
||||
contract.CountingResource = payload.countingResource.Value;
|
||||
contract.CountingResourceSpecified = true;
|
||||
}
|
||||
|
||||
contract.SpecifyingQualityIndicators = payload.specifyingQualityIndicators;
|
||||
|
||||
if (payload.noConnectionToWaterSupply)
|
||||
{
|
||||
contract.NoConnectionToWaterSupply = true;
|
||||
contract.NoConnectionToWaterSupplySpecified = true;
|
||||
}
|
||||
|
||||
contract.ObjectAddress = payload.objectAddress;
|
||||
contract.Quality = payload.quality;
|
||||
contract.OtherQualityIndicator = payload.otherQualityIndicator;
|
||||
contract.TemperatureChart = payload.temperatureChart;
|
||||
contract.BillingDate = payload.billingDate;
|
||||
contract.PaymentDate = payload.paymentDate;
|
||||
contract.ProvidingInformationDate = payload.providingInformationDate;
|
||||
|
||||
if (payload.meteringDeviceInformation.HasValue)
|
||||
{
|
||||
contract.MeteringDeviceInformation = payload.meteringDeviceInformation.Value;
|
||||
contract.MeteringDeviceInformationSpecified = true;
|
||||
}
|
||||
|
||||
if (payload.volumeDepends.HasValue)
|
||||
{
|
||||
contract.VolumeDepends = payload.volumeDepends.Value;
|
||||
contract.VolumeDependsSpecified = true;
|
||||
}
|
||||
|
||||
if (payload.oneTimePayment.HasValue)
|
||||
{
|
||||
contract.OneTimePayment = payload.oneTimePayment.Value;
|
||||
contract.OneTimePaymentSpecified = true;
|
||||
}
|
||||
|
||||
if (payload.accrualProcedure.HasValue)
|
||||
{
|
||||
contract.AccrualProcedure = payload.accrualProcedure.Value;
|
||||
contract.AccrualProcedureSpecified = true;
|
||||
}
|
||||
|
||||
contract.Tariff = payload.tariff;
|
||||
contract.Norm = payload.norm;
|
||||
|
||||
return contract;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,306 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.HouseManagement;
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.HouseManagement;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.HouseManagement
|
||||
{
|
||||
internal class ImportSupplyResourceContractProjectRequest(ClientBase client) : HouseManagementRequestBase(client)
|
||||
{
|
||||
protected override bool CanBeRestarted => false;
|
||||
|
||||
internal async Task<getStateResultImportResultCommonResultImportSupplyResourceContractProject> ExecuteAsync(ImportSupplyResourceContractProjectPayload payload, CancellationToken token)
|
||||
{
|
||||
ThrowIfPayloadIncorrect(payload);
|
||||
|
||||
// http://open-gkh.ru/HouseManagement/importSupplyResourceContractProjectRequest/Contract.html
|
||||
var contract = new importSupplyResourceContractProjectRequestContract
|
||||
{
|
||||
TransportGUID = Guid.NewGuid().ToString(),
|
||||
Item1 = GetContractFromPayload(payload)
|
||||
};
|
||||
|
||||
// http://open-gkh.ru/HouseManagement/importSupplyResourceContractProjectRequest.html
|
||||
var request = new importSupplyResourceContractProjectRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "11.7.0.3",
|
||||
Contract = [contract]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.importSupplyResourceContractProjectDataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
result.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
|
||||
var importResults = result.Items.OfType<getStateResultImportResult>();
|
||||
var commonResults = GetCommonResults(importResults);
|
||||
foreach (var commonResult in commonResults)
|
||||
{
|
||||
if (commonResult.ItemElementName == ItemChoiceType26.ImportSupplyResourceContractProject)
|
||||
{
|
||||
if (commonResult.Item is getStateResultImportResultCommonResultImportSupplyResourceContractProject importedContract)
|
||||
{
|
||||
return importedContract;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: Дополнить проверки
|
||||
private void ThrowIfPayloadIncorrect(ImportSupplyResourceContractProjectPayload payload)
|
||||
{
|
||||
if (string.IsNullOrEmpty(payload.contractNumber))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.contractNumber)} is empty");
|
||||
}
|
||||
|
||||
if (payload.signingDate.Equals(default) || payload.effectiveDate.Equals(default))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.signingDate)} OR/AND {nameof(payload.effectiveDate)} are default");
|
||||
}
|
||||
|
||||
if (!payload.comptetionDate.HasValue && payload.automaticRollOverOneYear)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.comptetionDate)} is null but {nameof(payload.automaticRollOverOneYear)} has value");
|
||||
}
|
||||
|
||||
if (payload.period == null && (payload.volumeDepends.HasValue && payload.volumeDepends.Value
|
||||
|| payload.meteringDeviceInformation.HasValue && payload.meteringDeviceInformation.Value))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.period)} is null but {nameof(payload.volumeDepends)} OR/AND {nameof(payload.meteringDeviceInformation)} have value");
|
||||
}
|
||||
|
||||
if (payload.indicationsAnyDay && payload.period == null)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.indicationsAnyDay)} has value but {nameof(payload.period)} is null");
|
||||
}
|
||||
|
||||
// TODO: Add counterparty check
|
||||
|
||||
if (payload.plannedVolumeType.HasValue && !payload.isPlannedVolume)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.plannedVolumeType)} has value but {nameof(payload.isPlannedVolume)} is false");
|
||||
}
|
||||
|
||||
if (payload.contractSubject == null || payload.contractSubject.Length == 0)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.contractSubject)} is empty");
|
||||
}
|
||||
|
||||
if (payload.contractSubject != null && payload.contractSubject.Length > 100)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.contractSubject)} exceeds its limit ({payload.contractSubject.Length} of 100)");
|
||||
}
|
||||
|
||||
if (payload.countingResource.HasValue && (!payload.accrualProcedure.HasValue ||
|
||||
payload.accrualProcedure.Value == SupplyResourceContractProjectTypeAccrualProcedure.O))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.countingResource)} has value but {nameof(payload.accrualProcedure)} is null OR has inappropriate value");
|
||||
}
|
||||
|
||||
// TODO: Add noConnectionToWaterSupply check
|
||||
// TODO: Add quality check
|
||||
// TODO: Add otherQualityIndicator check
|
||||
// TODO: Add temperatureChart check
|
||||
|
||||
if (payload.billingDate == null && (payload.counterparty is not SupplyResourceContractTypeOrganization ||
|
||||
payload.meteringDeviceInformation.HasValue))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.billingDate)} is null but {nameof(payload.meteringDeviceInformation)} has value");
|
||||
}
|
||||
|
||||
if (payload.billingDate != null && payload.oneTimePayment.HasValue && payload.oneTimePayment.Value)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.billingDate)} has value but {nameof(payload.oneTimePayment)} is true");
|
||||
}
|
||||
|
||||
if (payload.paymentDate == null && payload.counterparty is not SupplyResourceContractTypeOrganization &&
|
||||
payload.isContract && payload.oneTimePayment.HasValue && !payload.oneTimePayment.Value)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.paymentDate)} is null but should have value");
|
||||
}
|
||||
|
||||
if (payload.paymentDate != null && payload.oneTimePayment.HasValue && payload.oneTimePayment.Value)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.paymentDate)} has value but {nameof(payload.oneTimePayment)} is true");
|
||||
}
|
||||
|
||||
if (payload.providingInformationDate == null && payload.counterparty is SupplyResourceContractTypeOrganization &&
|
||||
payload.countingResource.HasValue && payload.countingResource.Value == SupplyResourceContractProjectTypeCountingResource.R &&
|
||||
payload.isContract)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.providingInformationDate)} is null but should have value");
|
||||
}
|
||||
|
||||
if (!payload.meteringDeviceInformation.HasValue &&
|
||||
payload.countingResource.HasValue && payload.countingResource == SupplyResourceContractProjectTypeCountingResource.R)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.meteringDeviceInformation)} is null but should have value");
|
||||
}
|
||||
|
||||
if (payload.volumeDepends.HasValue && (payload.counterparty is SupplyResourceContractTypeOrganization ||
|
||||
payload.oneTimePayment.HasValue && payload.oneTimePayment.Value))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.volumeDepends)} has value but should have not one");
|
||||
}
|
||||
|
||||
if (payload.oneTimePayment.HasValue && payload.counterparty is SupplyResourceContractTypeOrganization)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.oneTimePayment)} has value but {nameof(payload.counterparty)} has inappropriate value");
|
||||
}
|
||||
|
||||
// TODO: Add accrualProcedure check
|
||||
}
|
||||
|
||||
private SupplyResourceContractProjectType GetContractFromPayload(ImportSupplyResourceContractProjectPayload payload)
|
||||
{
|
||||
// http://open-gkh.ru/HouseManagement/SupplyResourceContractProjectType.html
|
||||
var contract = new SupplyResourceContractProjectType();
|
||||
|
||||
if (payload.isContract)
|
||||
{
|
||||
var isContract = new SupplyResourceContractProjectTypeIsContract()
|
||||
{
|
||||
ContractNumber = payload.contractNumber,
|
||||
SigningDate = payload.signingDate,
|
||||
EffectiveDate = payload.effectiveDate
|
||||
};
|
||||
contract.Item = isContract;
|
||||
}
|
||||
else
|
||||
{
|
||||
var isNotContract = new SupplyResourceContractProjectTypeIsNotContract()
|
||||
{
|
||||
ContractNumber = payload.contractNumber,
|
||||
SigningDate = payload.signingDate,
|
||||
SigningDateSpecified = true,
|
||||
EffectiveDate = payload.effectiveDate,
|
||||
EffectiveDateSpecified = true
|
||||
};
|
||||
contract.Item = isNotContract;
|
||||
}
|
||||
|
||||
var items = new List<object>();
|
||||
var itemsElementName = new List<ItemsChoiceType14>();
|
||||
if (payload.indefiniteTerm)
|
||||
{
|
||||
items.Add(payload.indefiniteTerm);
|
||||
itemsElementName.Add(ItemsChoiceType14.IndefiniteTerm);
|
||||
}
|
||||
if (payload.automaticRollOverOneYear)
|
||||
{
|
||||
items.Add(payload.automaticRollOverOneYear);
|
||||
itemsElementName.Add(ItemsChoiceType14.AutomaticRollOverOneYear);
|
||||
|
||||
items.Add(payload.comptetionDate.Value);
|
||||
itemsElementName.Add(ItemsChoiceType14.ComptetionDate);
|
||||
}
|
||||
if (items.Count > 0 && itemsElementName.Count > 0)
|
||||
{
|
||||
contract.Items = [.. items];
|
||||
contract.ItemsElementName = [.. itemsElementName];
|
||||
}
|
||||
|
||||
if (payload.period != null)
|
||||
{
|
||||
contract.Period = payload.period;
|
||||
}
|
||||
|
||||
if (payload.indicationsAnyDay)
|
||||
{
|
||||
contract.IndicationsAnyDay = true;
|
||||
contract.IndicationsAnyDaySpecified = true;
|
||||
}
|
||||
|
||||
if (payload.contractBase != null && payload.contractBase.Length > 0)
|
||||
{
|
||||
contract.ContractBase = payload.contractBase;
|
||||
}
|
||||
|
||||
contract.Item1 = payload.counterparty;
|
||||
contract.IsPlannedVolume = payload.isPlannedVolume;
|
||||
|
||||
if (payload.plannedVolumeType.HasValue)
|
||||
{
|
||||
contract.PlannedVolumeType = payload.plannedVolumeType.Value;
|
||||
contract.PlannedVolumeTypeSpecified = true;
|
||||
}
|
||||
|
||||
contract.ContractSubject = payload.contractSubject;
|
||||
|
||||
if (payload.countingResource.HasValue)
|
||||
{
|
||||
contract.CountingResource = payload.countingResource.Value;
|
||||
contract.CountingResourceSpecified = true;
|
||||
}
|
||||
|
||||
contract.SpecifyingQualityIndicators = payload.specifyingQualityIndicators;
|
||||
|
||||
if (payload.noConnectionToWaterSupply)
|
||||
{
|
||||
contract.NoConnectionToWaterSupply = true;
|
||||
contract.NoConnectionToWaterSupplySpecified = true;
|
||||
}
|
||||
|
||||
contract.Quality = payload.quality;
|
||||
contract.OtherQualityIndicator = payload.otherQualityIndicator;
|
||||
contract.TemperatureChart = payload.temperatureChart;
|
||||
contract.BillingDate = payload.billingDate;
|
||||
contract.PaymentDate = payload.paymentDate;
|
||||
contract.ProvidingInformationDate = payload.providingInformationDate;
|
||||
|
||||
if (payload.meteringDeviceInformation.HasValue)
|
||||
{
|
||||
contract.MeteringDeviceInformation = payload.meteringDeviceInformation.Value;
|
||||
contract.MeteringDeviceInformationSpecified = true;
|
||||
}
|
||||
|
||||
if (payload.volumeDepends.HasValue)
|
||||
{
|
||||
contract.VolumeDepends = payload.volumeDepends.Value;
|
||||
contract.VolumeDependsSpecified = true;
|
||||
}
|
||||
|
||||
if (payload.oneTimePayment.HasValue)
|
||||
{
|
||||
contract.OneTimePayment = payload.oneTimePayment.Value;
|
||||
contract.OneTimePaymentSpecified = true;
|
||||
}
|
||||
|
||||
if (payload.accrualProcedure.HasValue)
|
||||
{
|
||||
contract.AccrualProcedure = payload.accrualProcedure.Value;
|
||||
contract.AccrualProcedureSpecified = true;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(payload.regionCodeFias))
|
||||
{
|
||||
contract.RegionalSettings = new SupplyResourceContractProjectTypeRegionalSettings()
|
||||
{
|
||||
Region = new RegionType()
|
||||
{
|
||||
code = payload.regionCodeFias
|
||||
},
|
||||
Tariff = payload.tariff,
|
||||
Norm = payload.norm
|
||||
};
|
||||
}
|
||||
|
||||
return contract;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.Nsi;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.Nsi
|
||||
{
|
||||
internal class ExportDataProviderNsiItemRequest(ClientBase client) : NsiRequestBase(client)
|
||||
{
|
||||
internal async Task<IEnumerable<NsiItemType>> ExecuteAsync(exportDataProviderNsiItemRequestRegistryNumber registryNumber, CancellationToken token)
|
||||
{
|
||||
// http://open-gkh.ru/Nsi/exportDataProviderNsiItemRequest.html
|
||||
var request = new exportDataProviderNsiItemRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "10.0.1.2",
|
||||
RegistryNumber = registryNumber
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.exportDataProviderNsiItemAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
return result.Items.OfType<NsiItemType>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request;
|
||||
using Hcs.ClientNet.Api.Request.Adapter;
|
||||
using Hcs.Service.Async.Nsi;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.Service.Async.Nsi
|
||||
{
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResult : IGetStateResultMany { }
|
||||
#pragma warning restore IDE1006
|
||||
|
||||
public partial class NsiPortsTypeAsyncClient : IAsyncClient<RequestHeader>
|
||||
{
|
||||
public async Task<IGetStateResponse> GetStateAsync(RequestHeader header, IGetStateRequest request)
|
||||
{
|
||||
return await getStateAsync(header, (getStateRequest)request);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResponse : IGetStateResponse
|
||||
#pragma warning restore IDE1006
|
||||
{
|
||||
public IGetStateResult GetStateResult => getStateResult;
|
||||
}
|
||||
|
||||
public partial class AckRequestAck : IAck { }
|
||||
|
||||
public partial class ErrorMessageType : IErrorMessage { }
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateRequest : IGetStateRequest { }
|
||||
#pragma warning restore IDE1006
|
||||
}
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.Nsi
|
||||
{
|
||||
internal class NsiRequestBase(ClientBase client) :
|
||||
RequestBase<getStateResult,
|
||||
NsiPortsTypeAsyncClient,
|
||||
NsiPortsTypeAsync,
|
||||
RequestHeader,
|
||||
AckRequestAck,
|
||||
ErrorMessageType,
|
||||
getStateRequest>(client)
|
||||
{
|
||||
protected override EndPoint EndPoint => EndPoint.NsiAsync;
|
||||
|
||||
protected override bool EnableMinimalResponseWaitDelay => true;
|
||||
|
||||
protected override bool CanBeRestarted => true;
|
||||
|
||||
protected override int RestartTimeoutMinutes => 20;
|
||||
}
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.NsiCommon;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.NsiCommon
|
||||
{
|
||||
internal class ExportNsiItemRequest(ClientBase client) : NsiCommonRequestBase(client)
|
||||
{
|
||||
internal async Task<NsiItemType> ExecuteAsync(int registryNumber, ListGroup listGroup, CancellationToken token)
|
||||
{
|
||||
// http://open-gkh.ru/NsiCommon/exportNsiItemRequest.html
|
||||
var request = new exportNsiItemRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "10.0.1.2",
|
||||
RegistryNumber = registryNumber.ToString(),
|
||||
ListGroup = listGroup
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.exportNsiItemAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
return result.Item as NsiItemType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.NsiCommon;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.NsiCommon
|
||||
{
|
||||
internal class ExportNsiListRequest(ClientBase client) : NsiCommonRequestBase(client)
|
||||
{
|
||||
internal async Task<NsiListType> ExecuteAsync(ListGroup listGroup, CancellationToken token)
|
||||
{
|
||||
// http://open-gkh.ru/NsiCommon/exportNsiListRequest.html
|
||||
var request = new exportNsiListRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "10.0.1.2",
|
||||
ListGroup = listGroup
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.exportNsiListAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
return result.Item as NsiListType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request;
|
||||
using Hcs.ClientNet.Api.Request.Adapter;
|
||||
using Hcs.Service.Async.NsiCommon;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.Service.Async.NsiCommon
|
||||
{
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResult : IGetStateResultOne { }
|
||||
#pragma warning restore IDE1006
|
||||
|
||||
public partial class NsiPortsTypeAsyncClient : IAsyncClient<ISRequestHeader>
|
||||
{
|
||||
public async Task<IGetStateResponse> GetStateAsync(ISRequestHeader header, IGetStateRequest request)
|
||||
{
|
||||
return await getStateAsync(header, (getStateRequest)request);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResponse : IGetStateResponse
|
||||
#pragma warning restore IDE1006
|
||||
{
|
||||
public IGetStateResult GetStateResult => getStateResult;
|
||||
}
|
||||
|
||||
public partial class AckRequestAck : IAck { }
|
||||
|
||||
public partial class ErrorMessageType : IErrorMessage { }
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateRequest : IGetStateRequest { }
|
||||
#pragma warning restore IDE1006
|
||||
}
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.NsiCommon
|
||||
{
|
||||
internal class NsiCommonRequestBase(ClientBase client) :
|
||||
RequestBase<getStateResult,
|
||||
NsiPortsTypeAsyncClient,
|
||||
NsiPortsTypeAsync,
|
||||
ISRequestHeader,
|
||||
AckRequestAck,
|
||||
ErrorMessageType,
|
||||
getStateRequest>(client)
|
||||
{
|
||||
protected override EndPoint EndPoint => EndPoint.NsiCommonAsync;
|
||||
|
||||
protected override bool EnableMinimalResponseWaitDelay => true;
|
||||
|
||||
protected override bool CanBeRestarted => true;
|
||||
|
||||
protected override int RestartTimeoutMinutes => 20;
|
||||
}
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.OrgRegistryCommon;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.OrgRegistryCommon
|
||||
{
|
||||
internal class ExportDataProviderRequest(ClientBase client) : OrgRegistryCommonRequestBase(client)
|
||||
{
|
||||
internal async Task<IEnumerable<exportDataProviderResultType>> ExecuteAsync(bool isActual, CancellationToken token)
|
||||
{
|
||||
// http://open-gkh.ru/OrganizationsRegistryCommon/exportDataProviderRequest.html
|
||||
var request = new exportDataProviderRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "10.0.2.1"
|
||||
};
|
||||
|
||||
if (isActual)
|
||||
{
|
||||
request.IsActual = true;
|
||||
request.IsActualSpecified = true;
|
||||
}
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.exportDataProviderAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
return result.Items.OfType<exportDataProviderResultType>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.OrgRegistryCommon;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.OrgRegistryCommon
|
||||
{
|
||||
internal class ExportOrgRegistryRequest(ClientBase client) : OrgRegistryCommonRequestBase(client)
|
||||
{
|
||||
private const int OGRN_LENGTH = 13;
|
||||
|
||||
internal async Task<IEnumerable<exportOrgRegistryResultType>> ExecuteAsync(string ogrn, string kpp, CancellationToken token)
|
||||
{
|
||||
if (ogrn.Length != OGRN_LENGTH)
|
||||
{
|
||||
throw new System.ArgumentException($"The length of {ogrn} is incorrect");
|
||||
}
|
||||
|
||||
var criteria = new exportOrgRegistryRequestSearchCriteria();
|
||||
if (!string.IsNullOrEmpty(kpp))
|
||||
{
|
||||
criteria.Items = [ogrn, kpp];
|
||||
criteria.ItemsElementName = [ItemsChoiceType3.OGRN, ItemsChoiceType3.KPP];
|
||||
}
|
||||
else
|
||||
{
|
||||
criteria.Items = [ogrn];
|
||||
criteria.ItemsElementName = [ItemsChoiceType3.OGRN];
|
||||
}
|
||||
|
||||
// http://open-gkh.ru/OrganizationsRegistryCommon/exportOrgRegistryRequest.html
|
||||
var request = new exportOrgRegistryRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "10.0.2.1",
|
||||
SearchCriteria = [criteria]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.exportOrgRegistryAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
return result.Items.OfType<exportOrgRegistryResultType>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request;
|
||||
using Hcs.ClientNet.Api.Request.Adapter;
|
||||
using Hcs.Service.Async.OrgRegistryCommon;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.Service.Async.OrgRegistryCommon
|
||||
{
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResult : IGetStateResultMany { }
|
||||
#pragma warning restore IDE1006
|
||||
|
||||
public partial class RegOrgPortsTypeAsyncClient : IAsyncClient<ISRequestHeader>
|
||||
{
|
||||
public async Task<IGetStateResponse> GetStateAsync(ISRequestHeader header, IGetStateRequest request)
|
||||
{
|
||||
return await getStateAsync(header, (getStateRequest)request);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResponse : IGetStateResponse
|
||||
#pragma warning restore IDE1006
|
||||
{
|
||||
public IGetStateResult GetStateResult => getStateResult;
|
||||
}
|
||||
|
||||
public partial class AckRequestAck : IAck { }
|
||||
|
||||
public partial class ErrorMessageType : IErrorMessage { }
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateRequest : IGetStateRequest { }
|
||||
#pragma warning restore IDE1006
|
||||
}
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.OrgRegistryCommon
|
||||
{
|
||||
internal class OrgRegistryCommonRequestBase(ClientBase client) :
|
||||
RequestBase<getStateResult,
|
||||
RegOrgPortsTypeAsyncClient,
|
||||
RegOrgPortsTypeAsync,
|
||||
ISRequestHeader,
|
||||
AckRequestAck,
|
||||
ErrorMessageType,
|
||||
getStateRequest>(client)
|
||||
{
|
||||
protected override EndPoint EndPoint => EndPoint.OrgRegistryCommonAsync;
|
||||
|
||||
protected override bool EnableMinimalResponseWaitDelay => true;
|
||||
|
||||
protected override bool CanBeRestarted => true;
|
||||
|
||||
protected override int RestartTimeoutMinutes => 20;
|
||||
}
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request
|
||||
{
|
||||
internal class PaginationData
|
||||
{
|
||||
/// <summary>
|
||||
/// Состояние, указывающее на то, что это последняя страница
|
||||
/// </summary>
|
||||
internal bool IsLastPage { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Идентификатор следующей страницы
|
||||
/// </summary>
|
||||
internal Guid NextGuid { get; private set; }
|
||||
|
||||
public PaginationData(object item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new System.Exception($"[{nameof(PaginationData)}] item is null");
|
||||
}
|
||||
else if (item is bool boolItem)
|
||||
{
|
||||
if (boolItem == false)
|
||||
{
|
||||
throw new System.Exception($"[{nameof(PaginationData)}] item is false");
|
||||
}
|
||||
|
||||
IsLastPage = true;
|
||||
}
|
||||
else if (item is string stringItem)
|
||||
{
|
||||
IsLastPage = false;
|
||||
NextGuid = Guid.Parse(stringItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.Exception($"[{nameof(PaginationData)}] failed to handle item of {item.GetType().FullName} type");
|
||||
}
|
||||
}
|
||||
|
||||
internal static PaginationData CreateLastPageData()
|
||||
{
|
||||
return new PaginationData(true);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{nameof(PaginationData)}] {nameof(IsLastPage)} = {IsLastPage}" +
|
||||
(IsLastPage ? "" : $", {nameof(NextGuid)} = {NextGuid}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,111 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.Payments;
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.Payments;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.Payments
|
||||
{
|
||||
internal class ImportNotificationsOfOrderExecutionRequest(ClientBase client) : PaymentsRequestBase(client)
|
||||
{
|
||||
protected override bool CanBeRestarted => false;
|
||||
|
||||
internal async Task<bool> ExecuteAsync(ImportNotificationsOfOrderExecutionPayload payload, CancellationToken token)
|
||||
{
|
||||
ThrowIfPayloadIncorrect(payload);
|
||||
|
||||
// http://open-gkh.ru/Payment/importNotificationsOfOrderExecutionRequest.html
|
||||
var request = new importNotificationsOfOrderExecutionRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "10.0.1.1",
|
||||
Items = [GetNotificationFromPayload(payload)]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.importNotificationsOfOrderExecutionAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
result.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
|
||||
result.Items.OfType<CommonResultType>().ToList().ForEach(commonResult =>
|
||||
{
|
||||
commonResult.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ThrowIfPayloadIncorrect(ImportNotificationsOfOrderExecutionPayload payload)
|
||||
{
|
||||
if (string.IsNullOrEmpty(payload.orderId))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.orderId)} is empty");
|
||||
}
|
||||
|
||||
if (payload.month.HasValue && !payload.year.HasValue)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.month)} has value but {nameof(payload.year)} has not");
|
||||
}
|
||||
|
||||
if (!payload.month.HasValue && payload.year.HasValue)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.year)} has value but {nameof(payload.month)} has not");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(payload.paymentDocumentId))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.paymentDocumentId)} is empty");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(payload.paymentDocumentGUID))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.paymentDocumentGUID)} is empty");
|
||||
}
|
||||
}
|
||||
|
||||
private importNotificationsOfOrderExecutionRequestNotificationOfOrderExecution139Type GetNotificationFromPayload(ImportNotificationsOfOrderExecutionPayload payload)
|
||||
{
|
||||
var notification = new importNotificationsOfOrderExecutionRequestNotificationOfOrderExecution139Type()
|
||||
{
|
||||
TransportGUID = Guid.NewGuid().ToString(),
|
||||
OrderInfo = new NotificationOfOrderExecution139TypeOrderInfo()
|
||||
{
|
||||
OrderID = payload.orderId,
|
||||
OrderDate = payload.orderDate,
|
||||
Amount = payload.amount,
|
||||
Items = [payload.paymentDocumentId, payload.paymentDocumentGUID],
|
||||
ItemsElementName = [ItemsChoiceType4.PaymentDocumentID, ItemsChoiceType4.PaymentDocumentGUID]
|
||||
}
|
||||
};
|
||||
|
||||
if (payload.onlinePayment.HasValue && payload.onlinePayment.Value)
|
||||
{
|
||||
notification.OrderInfo.OnlinePayment = true;
|
||||
notification.OrderInfo.OnlinePaymentSpecified = true;
|
||||
}
|
||||
|
||||
if (payload.month.HasValue)
|
||||
{
|
||||
notification.OrderInfo.MonthAndYear = new NotificationOfOrderExecution139TypeOrderInfoMonthAndYear()
|
||||
{
|
||||
Year = payload.year.Value,
|
||||
Month = payload.month.Value
|
||||
};
|
||||
}
|
||||
|
||||
return notification;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,97 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Payload.Payments;
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.Service.Async.Payments;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.Payments
|
||||
{
|
||||
internal class ImportSupplierNotificationsOfOrderExecutionRequest(ClientBase client) : PaymentsRequestBase(client)
|
||||
{
|
||||
protected override bool CanBeRestarted => false;
|
||||
|
||||
internal async Task<bool> ExecuteAsync(ImportSupplierNotificationsOfOrderExecutionPayload payload, CancellationToken token)
|
||||
{
|
||||
ThrowIfPayloadIncorrect(payload);
|
||||
|
||||
// http://open-gkh.ru/Payment/importSupplierNotificationsOfOrderExecutionRequest.html
|
||||
var request = new importSupplierNotificationsOfOrderExecutionRequest
|
||||
{
|
||||
Id = Constants.SIGNED_XML_ELEMENT_ID,
|
||||
version = "10.0.1.1",
|
||||
SupplierNotificationOfOrderExecution = [GetNotificationFromPayload(payload)]
|
||||
};
|
||||
|
||||
var result = await SendAndWaitResultAsync(request, async asyncClient =>
|
||||
{
|
||||
var response = await asyncClient.importSupplierNotificationsOfOrderExecutionAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
result.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
|
||||
result.Items.OfType<CommonResultType>().ToList().ForEach(commonResult =>
|
||||
{
|
||||
commonResult.Items.OfType<ErrorMessageType>().ToList().ForEach(error =>
|
||||
{
|
||||
throw RemoteException.CreateNew(error.ErrorCode, error.Description);
|
||||
});
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ThrowIfPayloadIncorrect(ImportSupplierNotificationsOfOrderExecutionPayload payload)
|
||||
{
|
||||
if (payload.month.HasValue && !payload.year.HasValue)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.month)} has value but {nameof(payload.year)} has not");
|
||||
}
|
||||
|
||||
if (!payload.month.HasValue && payload.year.HasValue)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.year)} has value but {nameof(payload.month)} has not");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(payload.paymentDocumentId))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(payload.paymentDocumentId)} is empty");
|
||||
}
|
||||
}
|
||||
|
||||
private importSupplierNotificationsOfOrderExecutionRequestSupplierNotificationOfOrderExecution GetNotificationFromPayload(ImportSupplierNotificationsOfOrderExecutionPayload payload)
|
||||
{
|
||||
var notification = new importSupplierNotificationsOfOrderExecutionRequestSupplierNotificationOfOrderExecution()
|
||||
{
|
||||
TransportGUID = Guid.NewGuid().ToString(),
|
||||
OrderDate = payload.orderDate,
|
||||
Item = payload.paymentDocumentId,
|
||||
ItemElementName = ItemChoiceType1.PaymentDocumentID,
|
||||
Amount = payload.amount
|
||||
};
|
||||
|
||||
if (payload.month.HasValue)
|
||||
{
|
||||
notification.OrderPeriod = new SupplierNotificationOfOrderExecutionTypeOrderPeriod()
|
||||
{
|
||||
Month = payload.month.Value,
|
||||
Year = payload.year.Value
|
||||
};
|
||||
}
|
||||
|
||||
if (payload.onlinePayment.HasValue && payload.onlinePayment.Value)
|
||||
{
|
||||
notification.OnlinePayment = true;
|
||||
notification.OnlinePaymentSpecified = true;
|
||||
}
|
||||
|
||||
return notification;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request;
|
||||
using Hcs.ClientNet.Api.Request.Adapter;
|
||||
using Hcs.Service.Async.Payments;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.Service.Async.Payments
|
||||
{
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResult : IGetStateResultMany { }
|
||||
#pragma warning restore IDE1006
|
||||
|
||||
public partial class PaymentPortsTypeAsyncClient : IAsyncClient<RequestHeader>
|
||||
{
|
||||
public async Task<IGetStateResponse> GetStateAsync(RequestHeader header, IGetStateRequest request)
|
||||
{
|
||||
return await getStateAsync(header, (getStateRequest)request);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateResponse : IGetStateResponse
|
||||
#pragma warning restore IDE1006
|
||||
{
|
||||
public IGetStateResult GetStateResult => getStateResult;
|
||||
}
|
||||
|
||||
public partial class AckRequestAck : IAck { }
|
||||
|
||||
public partial class ErrorMessageType : IErrorMessage { }
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
public partial class getStateRequest : IGetStateRequest { }
|
||||
#pragma warning restore IDE1006
|
||||
}
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request.Payments
|
||||
{
|
||||
internal class PaymentsRequestBase(ClientBase client) :
|
||||
RequestBase<getStateResult,
|
||||
PaymentPortsTypeAsyncClient,
|
||||
PaymentPortsTypeAsync,
|
||||
RequestHeader,
|
||||
AckRequestAck,
|
||||
ErrorMessageType,
|
||||
getStateRequest>(client)
|
||||
{
|
||||
protected override EndPoint EndPoint => EndPoint.PaymentsAsync;
|
||||
|
||||
protected override bool EnableMinimalResponseWaitDelay => true;
|
||||
|
||||
protected override bool CanBeRestarted => true;
|
||||
|
||||
protected override int RestartTimeoutMinutes => 20;
|
||||
}
|
||||
}
|
||||
@ -1,423 +0,0 @@
|
||||
using Hcs.ClientNet.Api.Request.Adapter;
|
||||
using Hcs.ClientNet.Api.Request.Exception;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request
|
||||
{
|
||||
internal abstract class RequestBase<TResult, TAsyncClient, TChannel, TRequestHeader, TAck, TErrorMessage, TGetStateRequest>
|
||||
where TResult : IGetStateResult
|
||||
where TAsyncClient : ClientBase<TChannel>, TChannel, IAsyncClient<TRequestHeader>
|
||||
where TChannel : class
|
||||
where TRequestHeader : class
|
||||
where TAck : IAck
|
||||
where TErrorMessage : IErrorMessage
|
||||
where TGetStateRequest : IGetStateRequest, new()
|
||||
{
|
||||
private const int RESPONSE_WAIT_DELAY_MIN = 2;
|
||||
private const int RESPONSE_WAIT_DELAY_MAX = 5;
|
||||
|
||||
// "[EXP001000] Произошла ошибка при передаче данных. Попробуйте осуществить передачу данных повторно".
|
||||
// Видимо, эту ошибку нельзя включать здесь. Предположительно это маркер DDOS защиты и если отправлять
|
||||
// точно такой же пакет повторно, то ошибка входит в бесконечный цикл - необходимо заново
|
||||
// собирать пакет с новыми кодами и временем и новой подписью. Такую ошибку надо обнаруживать
|
||||
// на более высоком уровне и заново отправлять запрос новым пакетом.
|
||||
private static readonly string[] ignorableSystemErrorMarkers = [
|
||||
"Истекло время ожидания шлюза",
|
||||
"Базовое соединение закрыто: Соединение, которое должно было работать, было разорвано сервером",
|
||||
"Попробуйте осуществить передачу данных повторно",
|
||||
"(502) Недопустимый шлюз",
|
||||
"(503) Сервер не доступен"
|
||||
];
|
||||
|
||||
protected ClientBase client;
|
||||
protected CustomBinding binding;
|
||||
|
||||
protected abstract EndPoint EndPoint { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Для запросов, возвращающих мало данных, можно попробовать сократить
|
||||
/// начальный период ожидания подготовки ответа
|
||||
/// </summary>
|
||||
protected abstract bool EnableMinimalResponseWaitDelay { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Указывает на то, что можно ли этот метод перезапускать в случае зависания
|
||||
/// ожидания или в случае сбоя на сервере
|
||||
/// </summary>
|
||||
protected abstract bool CanBeRestarted { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Для противодействия зависанию ожидания вводится предел ожидания в минутах
|
||||
/// для запросов, которые можно перезапустить заново с теми же параметрами
|
||||
/// </summary>
|
||||
protected abstract int RestartTimeoutMinutes { get; }
|
||||
|
||||
private EndpointAddress RemoteAddress => new(client.ComposeEndpointUri(EndPointLocator.GetPath(EndPoint)));
|
||||
|
||||
private string ThreadIdText => $"(Thread #{ThreadId})";
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает идентификатор текущего исполняемого потока
|
||||
/// </summary>
|
||||
private int ThreadId => Environment.CurrentManagedThreadId;
|
||||
|
||||
public RequestBase(ClientBase client)
|
||||
{
|
||||
this.client = client;
|
||||
|
||||
ConfigureBinding();
|
||||
}
|
||||
|
||||
private void ConfigureBinding()
|
||||
{
|
||||
binding = new CustomBinding
|
||||
{
|
||||
CloseTimeout = TimeSpan.FromSeconds(180),
|
||||
OpenTimeout = TimeSpan.FromSeconds(180),
|
||||
ReceiveTimeout = TimeSpan.FromSeconds(180),
|
||||
SendTimeout = TimeSpan.FromSeconds(180)
|
||||
};
|
||||
|
||||
binding.Elements.Add(new TextMessageEncodingBindingElement
|
||||
{
|
||||
MessageVersion = MessageVersion.Soap11,
|
||||
WriteEncoding = Encoding.UTF8
|
||||
});
|
||||
|
||||
if (client.UseTunnel)
|
||||
{
|
||||
if (!System.Diagnostics.Process.GetProcessesByName("stunnel").Any())
|
||||
{
|
||||
throw new System.Exception("stunnel is not running");
|
||||
}
|
||||
|
||||
binding.Elements.Add(new HttpTransportBindingElement
|
||||
{
|
||||
AuthenticationScheme = (client.IsPPAK ? System.Net.AuthenticationSchemes.Digest : System.Net.AuthenticationSchemes.Basic),
|
||||
MaxReceivedMessageSize = int.MaxValue,
|
||||
UseDefaultWebProxy = false
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
binding.Elements.Add(new HttpsTransportBindingElement
|
||||
{
|
||||
AuthenticationScheme = (client.IsPPAK ? System.Net.AuthenticationSchemes.Digest : System.Net.AuthenticationSchemes.Basic),
|
||||
MaxReceivedMessageSize = int.MaxValue,
|
||||
RequireClientCertificate = true,
|
||||
UseDefaultWebProxy = false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task<TResult> SendAndWaitResultAsync(
|
||||
object request,
|
||||
Func<TAsyncClient, Task<TAck>> sender,
|
||||
CancellationToken token)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (CanBeRestarted)
|
||||
{
|
||||
return await RunRepeatableTaskInsistentlyAsync(
|
||||
async () => await ExecuteSendAndWaitResultAsync(request, sender, token), token);
|
||||
}
|
||||
else
|
||||
{
|
||||
return await ExecuteSendAndWaitResultAsync(request, sender, token);
|
||||
}
|
||||
}
|
||||
catch (RestartTimeoutException e)
|
||||
{
|
||||
if (!CanBeRestarted)
|
||||
{
|
||||
throw new System.Exception("Cannot restart request execution on timeout", e);
|
||||
}
|
||||
|
||||
client.TryLog($"Restarting {request.GetType().Name} request execution...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Для запросов к серверу которые можно направлять несколько раз, разрешаем
|
||||
/// серверу аномально отказаться. Предполагается, что здесь мы игнорируем
|
||||
/// только жесткие отказы серверной инфраструктуры, которые указывают
|
||||
/// что запрос даже не был принят в обработку. Также все запросы на
|
||||
/// чтение можно повторять в случае их серверных системных ошибок.
|
||||
/// </summary>
|
||||
protected async Task<TRepeatableResult> RunRepeatableTaskInsistentlyAsync<TRepeatableResult>(
|
||||
Func<Task<TRepeatableResult>> func, CancellationToken token)
|
||||
{
|
||||
var afterErrorDelaySec = 120;
|
||||
for (var attempt = 1; ; attempt++)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await func();
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
if (CanIgnoreSuchException(e, out string marker))
|
||||
{
|
||||
client.TryLog($"Ignoring error of attempt #{attempt} with type [{marker}]");
|
||||
client.TryLog($"Waiting {afterErrorDelaySec} sec until next attempt...");
|
||||
|
||||
await Task.Delay(afterErrorDelaySec * 1000, token);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e is RestartTimeoutException)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (e is RemoteException)
|
||||
{
|
||||
throw RemoteException.CreateNew(e as RemoteException);
|
||||
}
|
||||
|
||||
throw new System.Exception("Cannot ignore this exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanIgnoreSuchException(System.Exception e, out string resultMarker)
|
||||
{
|
||||
foreach (var marker in ignorableSystemErrorMarkers)
|
||||
{
|
||||
var found = Util.EnumerateInnerExceptions(e).Find(
|
||||
x => x.Message != null && x.Message.Contains(marker));
|
||||
if (found != null)
|
||||
{
|
||||
resultMarker = marker;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
resultMarker = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task<TResult> ExecuteSendAndWaitResultAsync(
|
||||
object request,
|
||||
Func<TAsyncClient, Task<TAck>> sender,
|
||||
CancellationToken token)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
}
|
||||
|
||||
var version = RequestHelper.GetRequestVersionString(request);
|
||||
client.TryLog($"Executing request {RemoteAddress.Uri}/{request.GetType().Name} of version {version}...");
|
||||
|
||||
TAck ack;
|
||||
|
||||
var stopWatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
using (var asyncClient = CreateAsyncClient())
|
||||
{
|
||||
ack = await sender(asyncClient);
|
||||
}
|
||||
stopWatch.Stop();
|
||||
|
||||
client.TryLog($"Request executed in {stopWatch.ElapsedMilliseconds} ms, result GUID is {ack.MessageGUID}");
|
||||
|
||||
var result = await WaitForResultAsync(ack, true, token);
|
||||
if (result is IQueryable queryableResult)
|
||||
{
|
||||
queryableResult.OfType<TErrorMessage>().ToList().ForEach(x =>
|
||||
{
|
||||
throw RemoteException.CreateNew(x.ErrorCode, x.Description);
|
||||
});
|
||||
}
|
||||
else if (result is TErrorMessage x)
|
||||
{
|
||||
throw RemoteException.CreateNew(x.ErrorCode, x.Description);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private TAsyncClient CreateAsyncClient()
|
||||
{
|
||||
var asyncClient = (TAsyncClient)Activator.CreateInstance(typeof(TAsyncClient), binding, RemoteAddress);
|
||||
ConfigureEndpointCredentials(asyncClient.Endpoint, asyncClient.ClientCredentials);
|
||||
return asyncClient;
|
||||
}
|
||||
|
||||
private void ConfigureEndpointCredentials(
|
||||
ServiceEndpoint serviceEndpoint, ClientCredentials clientCredentials)
|
||||
{
|
||||
serviceEndpoint.EndpointBehaviors.Add(new GostSigningEndpointBehavior(client));
|
||||
|
||||
if (!client.IsPPAK)
|
||||
{
|
||||
clientCredentials.UserName.UserName = Constants.NAME_SIT;
|
||||
clientCredentials.UserName.Password = Constants.PASSWORD_SIT;
|
||||
}
|
||||
|
||||
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate (
|
||||
object sender, X509Certificate serverCertificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!client.UseTunnel)
|
||||
{
|
||||
clientCredentials.ClientCertificate.SetCertificate(
|
||||
StoreLocation.CurrentUser,
|
||||
StoreName.My,
|
||||
X509FindType.FindByThumbprint,
|
||||
client.CertificateThumbprint);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Основной алгоритм ожидания ответа на асинхронный запрос.
|
||||
/// Из документации ГИС ЖКХ:
|
||||
/// Также рекомендуем придерживаться следующего алгоритма отправки запросов на получение статуса обработки пакета в случае использования асинхронных сервисов ГИС ЖКХ (в рамках одного MessageGUID):
|
||||
/// - первый запрос getState направлять не ранее чем через 10 секунд, после получения квитанции о приеме пакета с бизнес-данными от сервиса ГИС КЖХ;
|
||||
/// - в случае, если на первый запрос getSate получен результат с RequestState равным "1" или "2", то следующий запрос getState необходимо направлять не ранее чем через 60 секунд после отправки предыдущего запроса;
|
||||
/// - в случае, если на второй запрос getSate получен результат с RequestState равным "1" или "2", то следующий запрос getState необходимо направлять не ранее чем через 300 секунд после отправки предыдущего запроса;
|
||||
/// - в случае, если на третий запрос getSate получен результат с RequestState равным "1" или "2", то следующий запрос getState необходимо направлять не ранее чем через 900 секунд после отправки предыдущего запроса;
|
||||
/// - в случае, если на четвертый(и все последующие запросы) getState получен результат с RequestState равным "1" или "2", то следующий запрос getState необходимо направлять не ранее чем через 1800 секунд после отправки предыдущего запроса.
|
||||
/// </summary>
|
||||
private async Task<TResult> WaitForResultAsync(
|
||||
TAck ack, bool withInitialDelay, CancellationToken token)
|
||||
{
|
||||
TResult result;
|
||||
|
||||
var startTime = DateTime.Now;
|
||||
for (var attempts = 1; ; attempts++)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var delaySec = EnableMinimalResponseWaitDelay ? RESPONSE_WAIT_DELAY_MIN : RESPONSE_WAIT_DELAY_MAX;
|
||||
if (attempts >= 2)
|
||||
{
|
||||
delaySec = RESPONSE_WAIT_DELAY_MAX;
|
||||
}
|
||||
if (attempts >= 3)
|
||||
{
|
||||
delaySec = RESPONSE_WAIT_DELAY_MAX * 2;
|
||||
}
|
||||
if (attempts >= 5)
|
||||
{
|
||||
delaySec = RESPONSE_WAIT_DELAY_MAX * 4;
|
||||
}
|
||||
if (attempts >= 7)
|
||||
{
|
||||
delaySec = RESPONSE_WAIT_DELAY_MAX * 8;
|
||||
}
|
||||
if (attempts >= 9)
|
||||
{
|
||||
delaySec = RESPONSE_WAIT_DELAY_MAX * 16;
|
||||
}
|
||||
if (attempts >= 12)
|
||||
{
|
||||
delaySec = RESPONSE_WAIT_DELAY_MAX * 60;
|
||||
}
|
||||
|
||||
if (attempts > 1 || withInitialDelay)
|
||||
{
|
||||
var minutesElapsed = (int)(DateTime.Now - startTime).TotalMinutes;
|
||||
if (CanBeRestarted && minutesElapsed > RestartTimeoutMinutes)
|
||||
{
|
||||
throw new RestartTimeoutException($"{RestartTimeoutMinutes} minute(s) wait time exceeded");
|
||||
}
|
||||
|
||||
client.TryLog($"Waiting {delaySec} sec for attempt #{attempts}" +
|
||||
$" to get response ({minutesElapsed} minute(s) elapsed)...");
|
||||
|
||||
await Task.Delay(delaySec * 1000, token);
|
||||
}
|
||||
|
||||
client.TryLog($"Requesting response, attempt #{attempts} in {ThreadIdText}...");
|
||||
|
||||
result = await TryGetResultAsync(ack);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
client.TryLog($"Response received!");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Выполняет однократную проверку наличия результата.
|
||||
/// Возвращает default если результата еще нет.
|
||||
/// </summary>
|
||||
private async Task<TResult> TryGetResultAsync(TAck ack)
|
||||
{
|
||||
using var asyncClient = CreateAsyncClient();
|
||||
var requestHeader = RequestHelper.CreateHeader<TRequestHeader>(client);
|
||||
var requestBody = new TGetStateRequest
|
||||
{
|
||||
MessageGUID = ack.MessageGUID
|
||||
};
|
||||
var response = await asyncClient.GetStateAsync(requestHeader, requestBody);
|
||||
var result = response.GetStateResult;
|
||||
if (result.RequestState == (int)AsyncRequestStateType.Ready)
|
||||
{
|
||||
return (TResult)result;
|
||||
}
|
||||
return default;
|
||||
}
|
||||
|
||||
protected TRequestHeader CreateRequestHeader()
|
||||
{
|
||||
return RequestHelper.CreateHeader<TRequestHeader>(client);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Исполнение повторяемой операции некоторое допустимое число ошибок
|
||||
/// </summary>
|
||||
protected async Task<TRepeatableResult> RunRepeatableTaskAsync<TRepeatableResult>(
|
||||
Func<Task<TRepeatableResult>> taskFunc, Func<System.Exception, bool> canIgnoreFunc, int maxAttempts)
|
||||
{
|
||||
for (var attempts = 1; ; attempts++)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await taskFunc();
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
if (canIgnoreFunc(e))
|
||||
{
|
||||
if (attempts < maxAttempts)
|
||||
{
|
||||
client.TryLog($"Ignoring error of attempt #{attempts} of {maxAttempts} attempts");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new System.Exception("Too much attempts with error");
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,101 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request
|
||||
{
|
||||
internal static class RequestHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Подготовка заголовка сообщения отправляемого в ГИС ЖКХ с обязательными атрибутами.
|
||||
/// Заголовки могут быть разного типа для разных типов сообщений, но имена полей одинаковые.
|
||||
/// </summary>
|
||||
internal static THeader CreateHeader<THeader>(ClientBase client) where THeader : class
|
||||
{
|
||||
try
|
||||
{
|
||||
var instance = Activator.CreateInstance(typeof(THeader));
|
||||
foreach (var prop in instance.GetType().GetProperties())
|
||||
{
|
||||
switch (prop.Name)
|
||||
{
|
||||
case "Item":
|
||||
prop.SetValue(instance, client.OrgPPAGUID);
|
||||
break;
|
||||
|
||||
case "ItemElementName":
|
||||
prop.SetValue(instance, Enum.Parse(prop.PropertyType, "orgPPAGUID"));
|
||||
break;
|
||||
|
||||
case "MessageGUID":
|
||||
prop.SetValue(instance, Guid.NewGuid().ToString());
|
||||
break;
|
||||
|
||||
case "Date":
|
||||
prop.SetValue(instance, DateTime.Now);
|
||||
break;
|
||||
|
||||
case "IsOperatorSignatureSpecified":
|
||||
if (client.Role == OrganizationRole.RC || client.Role == OrganizationRole.RSO)
|
||||
{
|
||||
prop.SetValue(instance, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case "IsOperatorSignature":
|
||||
if (client.Role == OrganizationRole.RC || client.Role == OrganizationRole.RSO)
|
||||
{
|
||||
prop.SetValue(instance, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return instance as THeader;
|
||||
}
|
||||
catch (ArgumentNullException e)
|
||||
{
|
||||
throw new ApplicationException($"Error occured while building request header: {e.Message}");
|
||||
}
|
||||
catch (SystemException e)
|
||||
{
|
||||
throw new ApplicationException($"Error occured while building request header: {e.GetBaseException().Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Для объекта запроса возвращает значение строки свойства version
|
||||
/// </summary>
|
||||
internal static string GetRequestVersionString(object requestObject)
|
||||
{
|
||||
if (requestObject == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var versionHost = requestObject;
|
||||
if (versionHost != null)
|
||||
{
|
||||
var versionProperty = versionHost.GetType().GetProperties().FirstOrDefault(x => x.Name == "version");
|
||||
if (versionProperty != null)
|
||||
{
|
||||
return versionProperty.GetValue(versionHost) as string;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var field in requestObject.GetType().GetFields())
|
||||
{
|
||||
versionHost = field.GetValue(requestObject);
|
||||
if (versionHost != null)
|
||||
{
|
||||
var versionProperty = versionHost.GetType().GetProperties().FirstOrDefault(x => x.Name == "version");
|
||||
if (versionProperty != null)
|
||||
{
|
||||
return versionProperty.GetValue(versionHost) as string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,172 +0,0 @@
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using System;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Request
|
||||
{
|
||||
internal class X509Tools
|
||||
{
|
||||
private const string PRIVATE_KEY_USAGE_PERIOD = "2.5.29.16";
|
||||
|
||||
public static string GetFullnameWithExpirationDateStr(X509Certificate2 x509cert)
|
||||
{
|
||||
var (фамилия, имя, отчество) = GetFullname(x509cert);
|
||||
return (string.IsNullOrEmpty(фамилия) ? "" : $"{фамилия} ") + (string.IsNullOrEmpty(имя) ? "" : $"{имя} ") +
|
||||
(string.IsNullOrEmpty(отчество) ? "" : $"{отчество} ") + "until " + GetNotAfterDate(x509cert).ToString("dd.MM.yyyy");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает массив из трех строк, содержащих соответственно Фамилию, Имя и Отчество
|
||||
/// полученных из данных сертификата. Если сертификат не содержит ФИО, то возвращается массив
|
||||
/// из трех пустых строк. Это не точный метод определять имя, он предполагает, что
|
||||
/// поля SN, G, CN содержат ФИО в определенном порядке, что правдоподобно но не обязательно.
|
||||
/// </summary>
|
||||
private static (string Фамилия, string Имя, string Отчество) GetFullname(X509Certificate2 x509cert)
|
||||
{
|
||||
string фам = "", имя = "", отч = "";
|
||||
|
||||
// Сначала ищем поля surname (SN) и given-name (G)
|
||||
var sn = DecodeSubjectField(x509cert, "SN");
|
||||
var g = DecodeSubjectField(x509cert, "G");
|
||||
if (!string.IsNullOrEmpty(sn) && !string.IsNullOrEmpty(g))
|
||||
{
|
||||
фам = sn;
|
||||
|
||||
var gParts = g.Split(' ');
|
||||
if (gParts != null && gParts.Length >= 1)
|
||||
{
|
||||
имя = gParts[0];
|
||||
}
|
||||
if (gParts != null && gParts.Length >= 2)
|
||||
{
|
||||
отч = gParts[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Иначе берем три первых слова из common name (CN), игнорируя кавычки
|
||||
var cn = DecodeSubjectField(x509cert, "CN");
|
||||
if (!string.IsNullOrEmpty(cn))
|
||||
{
|
||||
cn = new StringBuilder(cn).Replace("\"", "").ToString();
|
||||
|
||||
char[] separators = [' ', ';'];
|
||||
var cnParts = cn.Split(separators);
|
||||
if (cnParts != null && cnParts.Length >= 1)
|
||||
{
|
||||
фам = cnParts[0];
|
||||
}
|
||||
if (cnParts != null && cnParts.Length >= 2)
|
||||
{
|
||||
имя = cnParts[1];
|
||||
}
|
||||
if (cnParts != null && cnParts.Length >= 3)
|
||||
{
|
||||
отч = cnParts[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (фам, имя, отч);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает значение поля с именем @subName включенного в различимое имя Subject
|
||||
/// </summary>
|
||||
private static string DecodeSubjectField(X509Certificate2 x509cert, string subName)
|
||||
{
|
||||
// Чтобы посмотреть все поля сертификата
|
||||
//System.Diagnostics.Trace.WriteLine("x509decode = " + x509cert.SubjectName.Decode(
|
||||
//X500DistinguishedNameFlags.UseNewLines));
|
||||
|
||||
// Декодируем различимое имя на отдельные строки через переводы строк для надежности разбора
|
||||
var decoded = x509cert.SubjectName.Decode(X500DistinguishedNameFlags.UseNewLines);
|
||||
char[] separators = ['\n', '\r'];
|
||||
var parts = decoded.Split(separators, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Каждая часть начинается с имени и отделяется от значения символом равно
|
||||
foreach (var part in parts)
|
||||
{
|
||||
if (part.Length <= subName.Length + 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (part.StartsWith(subName) && part[subName.Length] == '=')
|
||||
{
|
||||
return part.Substring(subName.Length + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает дату окончания действия сертификата
|
||||
/// </summary>
|
||||
private static DateTime GetNotAfterDate(X509Certificate2 x509cert)
|
||||
{
|
||||
// Сначала пытаемся определить срок первичного ключа, а затем уже самого сертификата
|
||||
var датаОкончания = GetPrivateKeyUsageEndDate(x509cert);
|
||||
if (датаОкончания != null)
|
||||
{
|
||||
return (DateTime)датаОкончания;
|
||||
}
|
||||
return x509cert.NotAfter;
|
||||
}
|
||||
|
||||
private static DateTime? GetPrivateKeyUsageEndDate(X509Certificate2 x509cert)
|
||||
{
|
||||
foreach (var ext in x509cert.Extensions)
|
||||
{
|
||||
if (ext.Oid.Value == PRIVATE_KEY_USAGE_PERIOD)
|
||||
{
|
||||
// Дата начала с индексом 0, дата окончания с индексом 1
|
||||
return ParseAsn1Datetime(ext, 1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Разбирает значение типа дата из серии значений ASN1 присоединенных к расширению
|
||||
/// </summary>
|
||||
private static DateTime? ParseAsn1Datetime(X509Extension ext, int valueIndex)
|
||||
{
|
||||
try
|
||||
{
|
||||
var asnObject = (new Asn1InputStream(ext.RawData)).ReadObject();
|
||||
if (asnObject == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var asnSequence = Asn1Sequence.GetInstance(asnObject);
|
||||
if (asnSequence.Count <= valueIndex)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var asn = (Asn1TaggedObject)asnSequence[valueIndex];
|
||||
var asnStr = Asn1OctetString.GetInstance(asn, false);
|
||||
var s = Encoding.UTF8.GetString(asnStr.GetOctets());
|
||||
var year = int.Parse(s.Substring(0, 4));
|
||||
var month = int.Parse(s.Substring(4, 2));
|
||||
var day = int.Parse(s.Substring(6, 2));
|
||||
var hour = int.Parse(s.Substring(8, 2));
|
||||
var minute = int.Parse(s.Substring(10, 2));
|
||||
var second = int.Parse(s.Substring(12, 2));
|
||||
return new DateTime(year, month, day, hour, minute, second);
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
using Hcs.Service.Async.Bills;
|
||||
using System;
|
||||
|
||||
namespace Hcs.ClientNet.Api.Type
|
||||
{
|
||||
// http://open-gkh.ru/Bills/PDServiceChargeType/MunicipalService/Consumption/Volume/determiningMethod.html
|
||||
public enum MunicipalServiceVolumeDeterminingMethod
|
||||
{
|
||||
Norm,
|
||||
MeteringDevice,
|
||||
Other
|
||||
}
|
||||
|
||||
internal static class MunicipalServiceVolumeDeterminingMethodExtensions
|
||||
{
|
||||
internal static PDServiceChargeTypeMunicipalServiceVolumeDeterminingMethod ToServiceType(this MunicipalServiceVolumeDeterminingMethod type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MunicipalServiceVolumeDeterminingMethod.Norm:
|
||||
return PDServiceChargeTypeMunicipalServiceVolumeDeterminingMethod.N;
|
||||
|
||||
case MunicipalServiceVolumeDeterminingMethod.MeteringDevice:
|
||||
return PDServiceChargeTypeMunicipalServiceVolumeDeterminingMethod.M;
|
||||
|
||||
case MunicipalServiceVolumeDeterminingMethod.Other:
|
||||
return PDServiceChargeTypeMunicipalServiceVolumeDeterminingMethod.O;
|
||||
}
|
||||
|
||||
throw new NotImplementedException($"Cannot convert {type} to service type");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,97 +0,0 @@
|
||||
using Hcs.ClientNet.Internal;
|
||||
using Hcs.ClientNet.Logger;
|
||||
using Hcs.ClientNet.MessageCapturer;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace Hcs.ClientNet
|
||||
{
|
||||
public abstract class ClientBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Идентификатор поставщика данных ГИС ЖКХ
|
||||
/// </summary>
|
||||
public string OrgPPAGUID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Исполнитель/сотрудник ГИС ЖКХ, от которого будут регистрироваться ответы
|
||||
/// </summary>
|
||||
public string ExecutorGUID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Признак, указывающий на то, что используется ли внешний туннель (stunnel)
|
||||
/// </summary>
|
||||
public bool UseTunnel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Если true, то запросы будут выполняться на промышленном стенде, иначе - на тестовом
|
||||
/// </summary>
|
||||
public bool IsPPAK { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Роль
|
||||
/// </summary>
|
||||
public OrganizationRole Role { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Устанавливаемый пользователем приемник отладочных сообщений
|
||||
/// </summary>
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Устанавливаемый пользователем механизм перехвата содержимого отправляемых
|
||||
/// и принимаемых пакетов
|
||||
/// </summary>
|
||||
public IMessageCapturer MessageCapturer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Сертификат клиента для применения при формировании запросов
|
||||
/// </summary>
|
||||
internal X509Certificate2 Certificate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Тип криптопровайдера, полученный из сертификата
|
||||
/// </summary>
|
||||
internal GostXades.CryptoProviderTypeEnum CryptoProviderType { get; set; }
|
||||
|
||||
internal GostCryptography.Base.ProviderType GostCryptoProviderType =>
|
||||
(GostCryptography.Base.ProviderType)CryptoProviderType;
|
||||
|
||||
/// <summary>
|
||||
/// Отпечаток сертификата
|
||||
/// </summary>
|
||||
internal string CertificateThumbprint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Пароль доступа к сертификату
|
||||
/// </summary>
|
||||
internal string CertificatePassword { get; set; }
|
||||
|
||||
internal string ComposeEndpointUri(string endpointName)
|
||||
{
|
||||
if (UseTunnel)
|
||||
{
|
||||
return $"http://{Constants.URI_TUNNEL}/{endpointName}";
|
||||
}
|
||||
|
||||
return IsPPAK
|
||||
? $"https://{Constants.URI_PPAK}/{endpointName}"
|
||||
: $"https://{Constants.URI_SIT_02}/{endpointName}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пробует вывести сообщение в установленный приемник отладочных сообщений
|
||||
/// </summary>
|
||||
internal void TryLog(string message)
|
||||
{
|
||||
Logger?.WriteLine(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пробует отправить тело сообщения в установленный перехватчик
|
||||
/// </summary>
|
||||
internal void TryCaptureMessage(bool sent, string messageBody)
|
||||
{
|
||||
MessageCapturer?.CaptureMessage(sent, messageBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
using GostCryptography.Base;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace Hcs.ClientNet.Internal
|
||||
{
|
||||
internal static class CertificateHelper
|
||||
{
|
||||
internal static bool IsGostPrivateKey(this X509Certificate2 certificate)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (certificate.HasPrivateKey)
|
||||
{
|
||||
var cspInfo = certificate.GetPrivateKeyInfo();
|
||||
if (cspInfo.ProviderType == (int)ProviderType.CryptoPro ||
|
||||
cspInfo.ProviderType == (int)ProviderType.VipNet ||
|
||||
cspInfo.ProviderType == (int)ProviderType.CryptoPro_2012_512 ||
|
||||
cspInfo.ProviderType == (int)ProviderType.CryptoPro_2012_1024)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal static GostXades.CryptoProviderTypeEnum GetProviderType(this X509Certificate2 certificate)
|
||||
{
|
||||
return (GostXades.CryptoProviderTypeEnum)GetProviderInfo(certificate).Item1;
|
||||
}
|
||||
|
||||
internal static Tuple<int, string> GetProviderInfo(this X509Certificate2 certificate)
|
||||
{
|
||||
if (certificate.HasPrivateKey)
|
||||
{
|
||||
var cspInfo = certificate.GetPrivateKeyInfo();
|
||||
return new Tuple<int, string>(cspInfo.ProviderType, cspInfo.ProviderName);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Certificate has no private key");
|
||||
}
|
||||
}
|
||||
|
||||
internal static X509Certificate2 FindCertificate(Func<X509Certificate2, bool> predicate)
|
||||
{
|
||||
if (predicate == null)
|
||||
{
|
||||
throw new ArgumentException("Null subject predicate");
|
||||
}
|
||||
|
||||
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
|
||||
try
|
||||
{
|
||||
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
|
||||
|
||||
var collection = store.Certificates
|
||||
.OfType<X509Certificate2>()
|
||||
.Where(x => x.HasPrivateKey && x.IsGostPrivateKey());
|
||||
|
||||
var now = DateTime.Now;
|
||||
return collection.First(
|
||||
x => now >= x.NotBefore && now <= x.NotAfter && predicate(x));
|
||||
}
|
||||
finally
|
||||
{
|
||||
store.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
namespace Hcs.ClientNet.Internal
|
||||
{
|
||||
internal static class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Имя XML-элемента в сообщении, которое будет подписываться в фильтре
|
||||
/// отправки подписывающем XML
|
||||
/// </summary>
|
||||
internal const string SIGNED_XML_ELEMENT_ID = "signed-data-container";
|
||||
|
||||
/// <summary>
|
||||
/// Если PIN сертификата не указан пользователем, применяется это значение
|
||||
/// по умолчанию для сертификатов RuToken
|
||||
/// </summary>
|
||||
internal const string DEFAULT_CERTIFICATE_PIN = "12345678";
|
||||
|
||||
internal const string URI_PPAK = "api.dom.gosuslugi.ru";
|
||||
internal const string URI_SIT_01 = "sit01.dom.test.gosuslugi.ru:10081";
|
||||
internal const string URI_SIT_02 = "sit02.dom.test.gosuslugi.ru:10081";
|
||||
internal const string URI_TUNNEL = "127.0.0.1:8080";
|
||||
|
||||
internal const string NAME_SIT = "sit";
|
||||
internal const string PASSWORD_SIT = "xw{p&&Ee3b9r8?amJv*]";
|
||||
}
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Hcs.ClientNet.Internal
|
||||
{
|
||||
internal static class Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Возвращает список все вложенных исключений для данного исключения
|
||||
/// </summary>
|
||||
internal static List<Exception> EnumerateInnerExceptions(Exception e)
|
||||
{
|
||||
var list = new List<Exception>();
|
||||
WalkInnerExceptionsRecurse(e, list);
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void WalkInnerExceptionsRecurse(Exception e, List<Exception> list)
|
||||
{
|
||||
if (e == null || list.Contains(e))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
list.Add(e);
|
||||
|
||||
WalkInnerExceptionsRecurse(e.InnerException, list);
|
||||
|
||||
if (e is AggregateException)
|
||||
{
|
||||
var aggregate = e as AggregateException;
|
||||
foreach (var inner in aggregate.InnerExceptions)
|
||||
{
|
||||
WalkInnerExceptionsRecurse(inner, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static string FormatDate(DateTime date)
|
||||
{
|
||||
return date.ToString("yyyyMMdd");
|
||||
}
|
||||
|
||||
internal static string FormatDate(DateTime? date)
|
||||
{
|
||||
return (date == null) ? string.Empty : FormatDate((DateTime)date);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Преобразует массиб байтов в строку в формате binhex
|
||||
/// </summary>
|
||||
internal static string ConvertToHexString(byte[] ba)
|
||||
{
|
||||
var buf = new StringBuilder(ba.Length * 2);
|
||||
foreach (byte b in ba)
|
||||
{
|
||||
buf.AppendFormat("{0:x2}", b);
|
||||
}
|
||||
return buf.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Hcs.ClientNet.Logger
|
||||
{
|
||||
public class ActionLogger : ILogger
|
||||
{
|
||||
public Action<string> OnWriteLine;
|
||||
|
||||
public void WriteLine(string message)
|
||||
{
|
||||
OnWriteLine?.Invoke(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Hcs.ClientNet.Logger
|
||||
{
|
||||
public class ConsoleLogger : ILogger
|
||||
{
|
||||
public void WriteLine(string message)
|
||||
{
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
namespace Hcs.ClientNet.Logger
|
||||
{
|
||||
/// <summary>
|
||||
/// Интерфейс для механизма вывода отладочных сообщений для обработки вызывающей системой
|
||||
/// </summary>
|
||||
public interface ILogger
|
||||
{
|
||||
internal void WriteLine(string message);
|
||||
}
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
using Hcs.ClientNet.Logger;
|
||||
using System.Text;
|
||||
|
||||
namespace Hcs.ClientNet.MessageCapturer
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация механизма захвата содержимого сообщений SOAP, записывающая
|
||||
/// каждое сообщение в отдельный файл на диске
|
||||
/// </summary>
|
||||
public class FileMessageCapturer(string directory, ILogger logger) : IMessageCapturer
|
||||
{
|
||||
private readonly string directory = directory;
|
||||
private readonly ILogger logger = logger;
|
||||
|
||||
public void CaptureMessage(bool sent, string messageBody)
|
||||
{
|
||||
var index = 0;
|
||||
var maxIndex = 1000000;
|
||||
string fileName;
|
||||
do
|
||||
{
|
||||
index += 1;
|
||||
|
||||
if (index > maxIndex)
|
||||
{
|
||||
throw new System.Exception("index value exceeds maxIndex value");
|
||||
}
|
||||
|
||||
fileName = index.ToString("D3") + "_" + (sent ? "message" : "response") + ".xml";
|
||||
|
||||
if (!string.IsNullOrEmpty(directory))
|
||||
{
|
||||
fileName = System.IO.Path.Combine(directory, fileName);
|
||||
}
|
||||
}
|
||||
while (System.IO.File.Exists(fileName));
|
||||
|
||||
logger?.WriteLine($"Capturing message to file {fileName}...");
|
||||
|
||||
System.IO.File.WriteAllText(fileName, messageBody, Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
namespace Hcs.ClientNet.MessageCapturer
|
||||
{
|
||||
/// <summary>
|
||||
/// Интерфейс для механизма захвата отправляемых и принимаемых
|
||||
/// SOAP сообщений в ходе коммуникации с ГИС ЖКХ
|
||||
/// </summary>
|
||||
public interface IMessageCapturer
|
||||
{
|
||||
internal void CaptureMessage(bool sent, string messageBody);
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Hcs.ClientNet.MessageCapturer
|
||||
{
|
||||
/// <summary>
|
||||
/// Реализация захвата содержимого отправляемых и принимаемых SOAP сообщений,
|
||||
/// которая хранит данные в памяти
|
||||
/// </summary>
|
||||
public class MemoryMessageCapturer : IMessageCapturer
|
||||
{
|
||||
private readonly MemoryStream messageCaptureStream;
|
||||
private readonly StreamWriter messageCaptureWriter;
|
||||
|
||||
public MemoryMessageCapturer()
|
||||
{
|
||||
messageCaptureStream = new MemoryStream();
|
||||
messageCaptureWriter = new StreamWriter(messageCaptureStream, Encoding.UTF8);
|
||||
}
|
||||
|
||||
public void CaptureMessage(bool sent, string messageBody)
|
||||
{
|
||||
if (messageCaptureStream.Position > 0)
|
||||
{
|
||||
messageCaptureWriter.WriteLine("");
|
||||
}
|
||||
|
||||
messageCaptureWriter.Write("<!--");
|
||||
messageCaptureWriter.Write(sent ? "SENT " : "RECEIVED ");
|
||||
messageCaptureWriter.Write(DateTime.Now.ToString());
|
||||
messageCaptureWriter.WriteLine("-->");
|
||||
messageCaptureWriter.Write(messageBody);
|
||||
messageCaptureWriter.Flush();
|
||||
}
|
||||
|
||||
public byte[] GetData()
|
||||
{
|
||||
var buf = messageCaptureStream.GetBuffer();
|
||||
var size = (int)messageCaptureStream.Length;
|
||||
var data = new byte[size];
|
||||
Buffer.BlockCopy(buf, 0, data, 0, size);
|
||||
return data;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Encoding.UTF8.GetString(GetData());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
namespace Hcs.ClientNet
|
||||
{
|
||||
public enum OrganizationRole
|
||||
{
|
||||
/// <summary>
|
||||
/// УК/ТСЖ/ЖСК
|
||||
/// </summary>
|
||||
UK,
|
||||
|
||||
/// <summary>
|
||||
/// Ресурсоснабжающая организация
|
||||
/// </summary>
|
||||
RSO,
|
||||
|
||||
/// <summary>
|
||||
/// Расчетный центр
|
||||
/// </summary>
|
||||
RC
|
||||
}
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
using GostCryptography.Gost_R3411;
|
||||
using Hcs.ClientNet.Api;
|
||||
using Hcs.ClientNet.Internal;
|
||||
using System;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace Hcs.ClientNet
|
||||
{
|
||||
/// <summary>
|
||||
/// Универсальный клиент для вызова всех реализованных функций интеграции с ГИС ЖКХ
|
||||
/// </summary>
|
||||
public class UniClient : ClientBase
|
||||
{
|
||||
public BillsApi Bills => new(this);
|
||||
|
||||
public DeviceMeteringApi DeviceMetering => new(this);
|
||||
|
||||
public HouseManagementApi HouseManagement => new(this);
|
||||
|
||||
public NsiApi Nsi => new(this);
|
||||
|
||||
public NsiCommonApi NsiCommon => new(this);
|
||||
|
||||
public OrgRegistryCommonApi OrgRegistryCommon => new(this);
|
||||
|
||||
public PaymentsApi Payments => new(this);
|
||||
|
||||
public void SetSigningCertificate(X509Certificate2 cert, string pin = null)
|
||||
{
|
||||
pin ??= Constants.DEFAULT_CERTIFICATE_PIN;
|
||||
|
||||
Certificate = cert ?? throw new ArgumentNullException("Certificate not specified");
|
||||
CryptoProviderType = cert.GetProviderType();
|
||||
CertificateThumbprint = cert.Thumbprint;
|
||||
CertificatePassword = pin;
|
||||
}
|
||||
|
||||
public X509Certificate2 FindCertificate(Func<X509Certificate2, bool> predicate)
|
||||
{
|
||||
return CertificateHelper.FindCertificate(predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Производит для потока хэш по алгоритму "ГОСТ Р 34.11-94" в строке binhex
|
||||
/// </summary>
|
||||
public string ComputeGost94Hash(System.IO.Stream stream)
|
||||
{
|
||||
// API HouseManagement указывает, что файлы приложенные к договору должны размещаться
|
||||
// с AttachmentHASH по стандарту ГОСТ. Оказывается, ГИС ЖКХ требует применения устаревшего
|
||||
// алгоритма ГОСТ Р 34.11-94 (соответствует `rhash --gost94-cryptopro file` в linux).
|
||||
using var algorithm = new Gost_R3411_94_HashAlgorithm(GostCryptoProviderType);
|
||||
var savedPosition = stream.Position;
|
||||
stream.Position = 0;
|
||||
var hashValue = Util.ConvertToHexString(algorithm.ComputeHash(stream));
|
||||
stream.Position = savedPosition;
|
||||
return hashValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
{
|
||||
"ExtendedData": {
|
||||
"inputs": [
|
||||
"../../HcsWsdlSources/wsdl_xsd_v.15.7.0.1/bills/hcs-bills-service-async.wsdl"
|
||||
],
|
||||
"collectionTypes": [
|
||||
"System.Array",
|
||||
"System.Collections.Generic.Dictionary`2"
|
||||
],
|
||||
"namespaceMappings": [
|
||||
"*, Hcs.Service.Async.Bills"
|
||||
],
|
||||
"targetFramework": "net8.0",
|
||||
"typeReuseMode": "All"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,16 +0,0 @@
|
||||
{
|
||||
"ExtendedData": {
|
||||
"inputs": [
|
||||
"../../HcsWsdlSources/wsdl_xsd_v.15.7.0.1/device-metering/hcs-device-metering-service-async.wsdl"
|
||||
],
|
||||
"collectionTypes": [
|
||||
"System.Array",
|
||||
"System.Collections.Generic.Dictionary`2"
|
||||
],
|
||||
"namespaceMappings": [
|
||||
"*, Hcs.Service.Async.DeviceMetering"
|
||||
],
|
||||
"targetFramework": "net8.0",
|
||||
"typeReuseMode": "All"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,16 +0,0 @@
|
||||
{
|
||||
"ExtendedData": {
|
||||
"inputs": [
|
||||
"../../HcsWsdlSources/wsdl_xsd_v.15.7.0.1/house-management/hcs-house-management-service-async.wsdl"
|
||||
],
|
||||
"collectionTypes": [
|
||||
"System.Array",
|
||||
"System.Collections.Generic.Dictionary`2"
|
||||
],
|
||||
"namespaceMappings": [
|
||||
"*, Hcs.Service.Async.HouseManagement"
|
||||
],
|
||||
"targetFramework": "net8.0",
|
||||
"typeReuseMode": "All"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,16 +0,0 @@
|
||||
{
|
||||
"ExtendedData": {
|
||||
"inputs": [
|
||||
"../../HcsWsdlSources/wsdl_xsd_v.15.7.0.1/nsi/hcs-nsi-service-async.wsdl"
|
||||
],
|
||||
"collectionTypes": [
|
||||
"System.Array",
|
||||
"System.Collections.Generic.Dictionary`2"
|
||||
],
|
||||
"namespaceMappings": [
|
||||
"*, Hcs.Service.Async.Nsi"
|
||||
],
|
||||
"targetFramework": "net8.0",
|
||||
"typeReuseMode": "All"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user