diff --git a/Hcs.Client/Client/Api/HouseManagementApi.cs b/Hcs.Client/Client/Api/HouseManagementApi.cs
index 3f03297..7c69edd 100644
--- a/Hcs.Client/Client/Api/HouseManagementApi.cs
+++ b/Hcs.Client/Client/Api/HouseManagementApi.cs
@@ -153,5 +153,17 @@ namespace Hcs.Client.Api
var request = new ImportSupplyResourceContractDataRequest(client);
return await request.ExecuteAsync(payload, token);
}
+
+ ///
+ /// Импорт проекта договора ресурсоснабжения с РСО
+ ///
+ /// Пейлоад проекта договора ресурсоснабжения
+ /// Токен отмены
+ /// Импортированный проект договора
+ public async Task ImportSupplyResourceContractProjectAsync(ImportSupplyResourceContractProjectPayload payload, CancellationToken token = default)
+ {
+ var request = new ImportSupplyResourceContractProjectRequest(client);
+ return await request.ExecuteAsync(payload, token);
+ }
}
}
diff --git a/Hcs.Client/Client/Api/Payload/HouseManagement/ImportSupplyResourceContractDataPayload.cs b/Hcs.Client/Client/Api/Payload/HouseManagement/ImportSupplyResourceContractDataPayload.cs
index b74ef87..a5a75a3 100644
--- a/Hcs.Client/Client/Api/Payload/HouseManagement/ImportSupplyResourceContractDataPayload.cs
+++ b/Hcs.Client/Client/Api/Payload/HouseManagement/ImportSupplyResourceContractDataPayload.cs
@@ -29,7 +29,7 @@ namespace Hcs.Client.Api.Payload.HouseManagement
public DateTime effectiveDate;
///
- /// Необязательное. Договор заключен на неопределенный срок или нет
+ /// Необязательное. Договор заключен на неопределенный срок или нет.
///
public bool indefiniteTerm;
@@ -70,7 +70,7 @@ namespace Hcs.Client.Api.Payload.HouseManagement
public nsiRef[] contractBase;
///
- /// Контрагент. Подходящие типы:
+ /// Вторая сторона договора. Подходящие типы:
/// ,
/// ,
/// ,
@@ -113,7 +113,7 @@ namespace Hcs.Client.Api.Payload.HouseManagement
/// Необязательное. Признак "Отсутствие присоединения сетей объектов жилищного фонда к централизованной
/// системе водоснабжения". Может быть указан, только если показатели качества коммунальных ресурсов
/// ведутся в разрезе договора и предмет договора включает коммунальную услугу "Холодное водоснабжение"
- /// И/ИЛИ "Горячее водоснабжение"/
+ /// И/ИЛИ "Горячее водоснабжение".
///
public bool noConnectionToWaterSupply;
diff --git a/Hcs.Client/Client/Api/Payload/HouseManagement/ImportSupplyResourceContractProjectPayload.cs b/Hcs.Client/Client/Api/Payload/HouseManagement/ImportSupplyResourceContractProjectPayload.cs
new file mode 100644
index 0000000..c33a916
--- /dev/null
+++ b/Hcs.Client/Client/Api/Payload/HouseManagement/ImportSupplyResourceContractProjectPayload.cs
@@ -0,0 +1,214 @@
+using Hcs.Service.Async.HouseManagement;
+using System;
+
+namespace Hcs.Client.Api.Payload.HouseManagement
+{
+ // http://open-gkh.ru/HouseManagement/SupplyResourceContractType.html
+ public class ImportSupplyResourceContractProjectPayload
+ {
+ ///
+ /// Если договор не является публичным и/или присутствует заключенный на бумажном носителе
+ /// (электронной форме) и/или не заключен в отношении нежилых помещений в многоквартирных домах,
+ /// то равно true, иначе - false
+ ///
+ public bool isContract;
+
+ ///
+ /// Номер договора
+ ///
+ public string contractNumber;
+
+ ///
+ /// Дата заключения
+ ///
+ public DateTime signingDate;
+
+ ///
+ /// Дата вступления в силу
+ ///
+ public DateTime effectiveDate;
+
+ ///
+ /// Необязательное. Договор заключен на неопределенный срок или нет.
+ ///
+ public bool indefiniteTerm;
+
+ ///
+ /// Необязательное. Автоматически пролонгировать договор на один год при наступлении
+ /// даты окончания действия или нет.
+ ///
+ public bool automaticRollOverOneYear;
+
+ ///
+ /// Условное. Дата окончания действия. Обязательно для заполнения, если
+ /// = true.
+ ///
+ public DateTime? comptetionDate;
+
+ ///
+ /// Условное. Период передачи текущих показаний по индивидуальным приборам учета. Обязателен для
+ /// заполнения, если поле = true ИЛИ если поле
+ /// = true.
+ ///
+ public SupplyResourceContractProjectTypePeriod period;
+
+ ///
+ /// Необязательное. Показывает, разрешена ли гражданам передача текущих показаний по
+ /// индивидуальным приборам учета в любой день месяца. Заполнение возможно только если: в настройках
+ /// организации установлена настройка "Разрешить передачу гражданам показаний индивидуальных или общих
+ /// (квартирных) приборов учета в любой день месяца" ИЛИ в настройках организации установлена настройка
+ /// "Разрешить передачу гражданам показаний индивидуальных или общих (квартирных) приборов учета только
+ /// в сроки, установленные в договоре, или в любой день месяца, если в договоре установлен признак
+ /// "Разрешить передачу показаний приборов учета в любой день месяца" И заполнен .
+ ///
+ public bool indicationsAnyDay;
+
+ ///
+ /// Необязательное. Ссылка на НСИ "Основание заключения договора" (реестровый номер 58). Значения
+ /// брать из .
+ ///
+ public nsiRef[] contractBase;
+
+ ///
+ /// Вторая сторона договора. Подходящие типы:
+ /// ,
+ /// ,
+ /// ,
+ /// ,
+ /// либо true, если это договор оферты.
+ ///
+ public object counterparty;
+
+ ///
+ /// Если в договоре в наличии плановый объем и режим подачи поставки ресурсов то true, иначе - false
+ ///
+ public bool isPlannedVolume;
+
+ ///
+ /// Необязательное. Тип ведения планового объема и режима подачи: D - в разрезе договора,
+ /// O - в разрезе объектов жилищного фонда. Заполняется при наличии в договоре планового объема и
+ /// режима поставки ресурсов.
+ ///
+ public SupplyResourceContractProjectTypePlannedVolumeType? plannedVolumeType;
+
+ ///
+ /// Предмет договора. Максимум 100 записей.
+ ///
+ public SupplyResourceContractProjectTypeContractSubject[] contractSubject;
+
+ ///
+ /// Условное. Размещение информации о начислениях за коммунальные услуги осуществляет: R(SO)- РСО,
+ /// P(roprietor) - исполнитель коммунальных услуг. Заполняется, если порядок размещения информации
+ /// о начислениях за коммунальные услуги ведется в разрезе договора.
+ ///
+ public SupplyResourceContractProjectTypeCountingResource? countingResource;
+
+ ///
+ /// Показатели качества коммунальных ресурсов и температурный график ведутся: D - в разрезе договора,
+ /// O - в разрезе объектов жилищного фонда
+ ///
+ public SupplyResourceContractProjectTypeSpecifyingQualityIndicators specifyingQualityIndicators;
+
+ ///
+ /// Необязательное. Признак "Отсутствие присоединения сетей объектов жилищного фонда к централизованной
+ /// системе водоснабжения". Может быть указан, только если показатели качества коммунальных ресурсов
+ /// ведутся в разрезе договора и предмет договора включает коммунальную услугу "Холодное водоснабжение"
+ /// И/ИЛИ "Горячее водоснабжение".
+ ///
+ public bool noConnectionToWaterSupply;
+
+ ///
+ /// Необязательное. Показатель качества (содержащийся в справочнике показателей качества). Обязательно
+ /// для заполнения, если показатели качества указываются в разрезе договора. Для пары КУ и КР
+ /// "Горячее водоснабжение" и "Питьевая вода" указываются актуальные показатели, определенные для КР
+ /// "Горячая вода" в справочнике показателей качества коммунальных ресурсов. Для пары КУ и КР
+ /// "Горячее водоснабжение" и "Тепловая энергия" информация о показателях качества не заполняется
+ /// только в том случае, если для договора (если показатели ведутся в разрезе договора) или
+ /// ОЖФ в договоре (если показатели ведутся в разрезе ОЖФ) также указана пара КУ и КР
+ /// "Горячее водоснабжение" и "Питьевая вода".
+ ///
+ public SupplyResourceContractProjectTypeQuality[] quality;
+
+ ///
+ /// Необязательное. Иной показатель качества коммунального ресурса (не содержащийся в справочнике
+ /// показателей качества).
+ ///
+ public SupplyResourceContractProjectTypeOtherQualityIndicator[] otherQualityIndicator;
+
+ ///
+ /// Необязательное. Информация о температурном графике. Доступно для заполнения только если в
+ /// предмете договора хотя бы раз встречается ресурс "Тепловая энергия".
+ ///
+ public SupplyResourceContractProjectTypeTemperatureChart[] temperatureChart;
+
+ ///
+ /// Условное. Срок представления (выставления) платежных документов, не позднее. Является
+ /// обязательным, если вторая сторона договора отличается от "Управляющая организация" ИЛИ если
+ /// заполнено поле . Не заполняется, если
+ /// = true.
+ ///
+ public SupplyResourceContractProjectTypeBillingDate billingDate;
+
+ ///
+ /// Условное. Срок внесения платы, не позднее. Является обязательным, если вторая сторона договора
+ /// отличается от "Управляющая организация" И договор не является публичным и/или присутствует
+ /// заключенный на бумажном носителе или в электронной форме И в поле
+ /// = false. Не заполняется, если = true.
+ ///
+ public SupplyResourceContractProjectTypePaymentDate paymentDate;
+
+ ///
+ /// Условное. Срок предоставления информации о поступивших платежах, не позднее. Является
+ /// обязательным, если второй стороной договора является "Управляющая организация",
+ /// "Размещение информации о начислениях за коммунальные услуги осуществляет" = "РСО" И
+ /// договор не является публичным и/или присутствует заключенный на бумажном носителе или в
+ /// электронной форме.
+ ///
+ public SupplyResourceContractProjectTypeProvidingInformationDate providingInformationDate;
+
+ ///
+ /// Условное. Указывает на то, что размещение информации об индивидуальных приборах учета и их
+ /// показаниях осуществляет ресурсоснабжающая организация или нет. Обязательно для заполнения,
+ /// если в указано "РСО". В остальных случаях не заполняется.
+ ///
+ public bool? meteringDeviceInformation;
+
+ ///
+ /// Необязательное. Указывает на то, что объем поставки ресурса(ов) определяется на основании прибора
+ /// учета или нет. Поле не заполняется, если вторая сторона договора "Управляющая организация"
+ /// ИЛИ поле = true.
+ ///
+ public bool? volumeDepends;
+
+ ///
+ /// Необязательное. Указывает на то, что оплата предоставленных услуг осуществляется ли единоразово
+ /// при отгрузке указанных ресурсов без заведения лицевых счетов для потребителей. Доступно
+ /// для заполнения, только если вторая сторона договора отлична от "Управляющая организация".
+ ///
+ public bool? oneTimePayment;
+
+ ///
+ /// Необязательное. Порядок размещения информации о начислениях за коммунальные услуги ведется: D - в
+ /// разрезе договора, O - в разрезе объектов жилищного фонда. Заполняется, если второй стороной договора
+ /// является исполнитель коммунальных услуг.
+ ///
+ public SupplyResourceContractProjectTypeAccrualProcedure? accrualProcedure;
+
+ ///
+ /// Кода ФИАС региона РФ, в котором применяются тарифы и/или нормативы потребления КУ (у поставщика
+ /// данных должна быть подтвержденная функция РСО в этом Субъекте РФ).
+ ///
+ public string regionCodeFias;
+
+ ///
+ /// Необязательное. Информация о применяемом тарифе. Заполнется при указании .
+ ///
+ public SupplyResourceContractProjectTypeRegionalSettingsTariff[] tariff;
+
+ ///
+ /// Необязательное. Информация о нормативе потребления коммунальной услуги. Заполнется при
+ /// указании .
+ ///
+ public SupplyResourceContractProjectTypeRegionalSettingsNorm[] norm;
+ }
+}
diff --git a/Hcs.Client/Client/Api/Request/HouseManagement/ImportSupplyResourceContractProjectRequest.cs b/Hcs.Client/Client/Api/Request/HouseManagement/ImportSupplyResourceContractProjectRequest.cs
new file mode 100644
index 0000000..fd9ff59
--- /dev/null
+++ b/Hcs.Client/Client/Api/Request/HouseManagement/ImportSupplyResourceContractProjectRequest.cs
@@ -0,0 +1,304 @@
+using Hcs.Client.Api.Payload.HouseManagement;
+using Hcs.Client.Api.Request.Exception;
+using Hcs.Client.Internal;
+using Hcs.Service.Async.HouseManagement;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Hcs.Client.Api.Request.HouseManagement
+{
+ internal class ImportSupplyResourceContractProjectRequest(ClientBase client) : HouseManagementRequestBase(client)
+ {
+ protected override bool CanBeRestarted => false;
+
+ internal async Task 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().ToList().ForEach(error =>
+ {
+ throw RemoteException.CreateNew(error.ErrorCode, error.Description);
+ });
+
+ var importResults = result.Items.OfType();
+ 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,
+ EffectiveDate = payload.effectiveDate
+ };
+ contract.Item = isNotContract;
+ }
+
+ var items = new List