Add project
Basic formatting applied. Unnecessary comments have been removed. Suspicious code is covered by TODO.
This commit is contained in:
@ -0,0 +1,132 @@
|
||||
using Hcs.ClientApi.DataTypes;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Метод получения из ГИС ЖКХ полного реестра договоров ресурсоснабжения
|
||||
/// и всех связанных с ними лицевых счетов и приборов учета
|
||||
/// </summary>
|
||||
internal class HcsContractRegistryDownloader
|
||||
{
|
||||
private HcsHouseManagementApi api;
|
||||
|
||||
internal HcsContractRegistryDownloader(HcsHouseManagementApi api)
|
||||
{
|
||||
this.api = api;
|
||||
}
|
||||
|
||||
private void ThrowOperationCancelled()
|
||||
{
|
||||
throw new HcsException("Операция прервана пользователем");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получить все договоры РСО удовлетворяющие фильтру @фильтрДоговоров
|
||||
/// с подчиненными объектами (ЛС и ПУ)
|
||||
/// </summary>
|
||||
internal async Task<ГисДоговорыИПриборы> ПолучитьВсеДоговорыИПриборы(
|
||||
Func<ГисДоговор, bool> фильтрДоговоров, CancellationToken token)
|
||||
{
|
||||
// TODO: Проверить комментарий
|
||||
// В процессе будет много запросов, возвращающих мало данных,
|
||||
// но требующих стандартного ожидания в несколько секунд, что
|
||||
// суммарно складывается в целые часы. Экспериментально установлено
|
||||
// что ГИС ЖКХ способна пережить некоторую параллельность запросов
|
||||
// к ней. Так, с параллельностью в 5 потоков получение данных
|
||||
// по 3000 договорам РСО (70000 ПУ) длится 2,5 часа.
|
||||
int числоПотоковПараллельности = 5;
|
||||
|
||||
var все = new ГисДоговорыИПриборы();
|
||||
все.ДатаНачалаСборки = DateTime.Now;
|
||||
|
||||
Action<ГисДоговор> обработчикДоговора = (ГисДоговор договор) =>
|
||||
{
|
||||
if (фильтрДоговоров(договор)) все.ДоговорыРСО.Add(договор);
|
||||
};
|
||||
await api.ПолучитьДоговорыРСО(обработчикДоговора, token);
|
||||
|
||||
int сделаноДоговоров = 0;
|
||||
Action<ГисАдресныйОбъект> обработчикАдреса = все.АдресаОбъектов.Add;
|
||||
Func<ГисДоговор, Task> обработчикДоговораАдреса = async (договор) =>
|
||||
{
|
||||
if (token.IsCancellationRequested) ThrowOperationCancelled();
|
||||
api.Config.Log($"Получаем адреса договора #{++сделаноДоговоров}/{все.ДоговорыРСО.Count()}...");
|
||||
await api.ПолучитьАдресаДоговораРСО(договор, обработчикАдреса, token);
|
||||
};
|
||||
await HcsParallel.ForEachAsync(все.ДоговорыРСО, обработчикДоговораАдреса, числоПотоковПараллельности);
|
||||
|
||||
var гуидыЗданий = все.АдресаОбъектов.Select(x => x.ГуидЗданияФиас).Distinct();
|
||||
|
||||
int сделаноЗданий = 0;
|
||||
Func<Guid, Task> обработчикЗдания = async (гуидЗдания) =>
|
||||
{
|
||||
if (token.IsCancellationRequested) ThrowOperationCancelled();
|
||||
api.Config.Log($"Получаем помещения здания #{++сделаноЗданий}/{гуидыЗданий.Count()}...");
|
||||
try
|
||||
{
|
||||
var здание = await api.ПолучитьЗданиеПоГуидФиас(гуидЗдания, token);
|
||||
все.Здания.Add(здание);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (HcsRemoteException.ContainsErrorCode(e, HcsRemoteException.KnownCodes.ОтсутствуетВРеестре))
|
||||
{
|
||||
api.Config.Log($"Не удалось получить здание по ФИАС ГУИД {гуидЗдания}: здание отсутствует в реестре");
|
||||
var здание = new ГисЗдание() { ГуидЗданияФиас = гуидЗдания };
|
||||
все.Здания.Add(здание);
|
||||
}
|
||||
else if (HcsRemoteException.ContainsErrorCode(e, HcsRemoteException.KnownCodes.ДоступЗапрещен))
|
||||
{
|
||||
api.Config.Log($"Не удалось получить здание по ФИАС ГУИД {гуидЗдания}: доступ запрещен");
|
||||
var здание = new ГисЗдание() { ГуидЗданияФиас = гуидЗдания };
|
||||
все.Здания.Add(здание);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new HcsException($"Вложенная ошибка получения здания {гуидЗдания}", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
await HcsParallel.ForEachAsync(гуидыЗданий, обработчикЗдания, числоПотоковПараллельности);
|
||||
|
||||
сделаноЗданий = 0;
|
||||
Action<ГисЛицевойСчет> обработчикЛС = (ГисЛицевойСчет лс) =>
|
||||
{
|
||||
if (лс.ДействуетСейчас && все.ЭтотЛицевойСчетСвязанСДоговорами(лс))
|
||||
{
|
||||
все.ЛицевыеСчета.Add(лс);
|
||||
}
|
||||
};
|
||||
Func<Guid, Task> обработчикЗданияЛС = async (гуидЗдания) =>
|
||||
{
|
||||
if (token.IsCancellationRequested) ThrowOperationCancelled();
|
||||
api.Config.Log($"Получаем ЛС по зданию #{++сделаноЗданий}/{гуидыЗданий.Count()}...");
|
||||
await api.ПолучитьЛицевыеСчетаПоЗданию(гуидЗдания, обработчикЛС, token);
|
||||
};
|
||||
await HcsParallel.ForEachAsync(гуидыЗданий, обработчикЗданияЛС, числоПотоковПараллельности);
|
||||
|
||||
сделаноЗданий = 0;
|
||||
Action<ГисПриборУчета> обработчикПУ = (ГисПриборУчета прибор) =>
|
||||
{
|
||||
if (прибор.ЭтоАктивный && (прибор.ЭтоОДПУ || все.ЭтотПриборСвязанСЛицевымиСчетами(прибор)))
|
||||
{
|
||||
все.ПриборыУчета.Add(прибор);
|
||||
}
|
||||
};
|
||||
Func<Guid, Task> обработчикЗданияПУ = async (гуидЗдания) =>
|
||||
{
|
||||
if (token.IsCancellationRequested) ThrowOperationCancelled();
|
||||
api.Config.Log($"Получаем ПУ по зданию #{++сделаноЗданий}/{гуидыЗданий.Count()}...");
|
||||
await api.ПолучитьПриборыУчетаПоЗданию(гуидЗдания, обработчикПУ, token);
|
||||
};
|
||||
await HcsParallel.ForEachAsync(гуидыЗданий, обработчикЗданияПУ, числоПотоковПараллельности);
|
||||
|
||||
все.ДатаКонцаСборки = DateTime.Now;
|
||||
return все;
|
||||
}
|
||||
}
|
||||
}
|
||||
189
Hcs.Client/ClientApi/HouseManagementApi/HcsHouseManagementApi.cs
Normal file
189
Hcs.Client/ClientApi/HouseManagementApi/HcsHouseManagementApi.cs
Normal file
@ -0,0 +1,189 @@
|
||||
using Hcs.ClientApi.DataTypes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Методы ГИС ЖКХ сервиса hcs-house-management (Договоры, ЛицевыеСчета, Приборы учета)
|
||||
/// </summary>
|
||||
public class HcsHouseManagementApi
|
||||
{
|
||||
public HcsClientConfig Config { get; private set; }
|
||||
|
||||
public HcsHouseManagementApi(HcsClientConfig config)
|
||||
{
|
||||
this.Config = config;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Размещает договор и возвращает дату размещения
|
||||
/// </summary>
|
||||
public async Task<DateTime> РазместитьДоговор(
|
||||
ГисДоговор договор, IEnumerable<ГисАдресныйОбъект> адреса, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodImportSupplyResourceContractData(Config);
|
||||
return await method.ImportContract(договор, адреса, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Размещает лицевой счет и возвращает его ЕЛС
|
||||
/// </summary>
|
||||
public async Task<string> РазместитьЛицевойСчет(
|
||||
ГисДоговор договор, ГисЛицевойСчет лицевойСчет, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodImportAccountData(Config);
|
||||
return await method.ImportAccount(договор, лицевойСчет, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Размещает прибор учета и возвращает его ГУИД
|
||||
/// </summary>
|
||||
public async Task<Guid> РазместитьПриборУчета(
|
||||
ГисПриборУчета прибор, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodImportMeteringDeviceData(Config);
|
||||
return await method.ImportMeteringDevice(прибор, token);
|
||||
}
|
||||
|
||||
public async Task<DateTime> АрхивироватьПриборУчета(
|
||||
ГисПриборУчета прибор, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodImportMeteringDeviceData(Config);
|
||||
return await method.ArchiveMeteringDevice(прибор, token);
|
||||
}
|
||||
|
||||
public async Task<DateTime> РасторгнутьДоговор(
|
||||
ГисДоговор договор, DateTime датаРасторжения, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodImportSupplyResourceContractData(Config);
|
||||
return await method.TerminateContract(договор, датаРасторжения, token);
|
||||
}
|
||||
|
||||
public async Task<DateTime> АннулироватьДоговор(
|
||||
ГисДоговор договор, string причина, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodImportSupplyResourceContractData(Config);
|
||||
return await method.AnnulContract(договор, причина, token);
|
||||
}
|
||||
|
||||
public async Task УдалитьПроектДоговора(
|
||||
ГисДоговор договор, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodImportSupplyResourceContractProject(Config);
|
||||
await method.DeleteContractProject(договор, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Переводит проект договора в состояние "Размещен"
|
||||
/// </summary>
|
||||
public async Task РазместитьПроектДоговора(
|
||||
ГисДоговор договор, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodImportSupplyResourceContractProject(Config);
|
||||
await method.PlaceContractProject(договор, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение одного договора ресурсоснабжения по его ГУИД.
|
||||
/// Если такого договора нет, будет выброшено HcsNoResultsRemoteException.
|
||||
/// </summary>
|
||||
public async Task<ГисДоговор> ПолучитьДоговорРСО(
|
||||
Guid гуидДоговора, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodExportSupplyResourceContractData(Config);
|
||||
method.EnableMinimalResponseWaitDelay = true;
|
||||
return await method.QueryOne(гуидДоговора, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение одного договора ресурсоснабжения по его номеру.
|
||||
/// Если такого договора нет, будет выброшено HcsNoResultsRemoteException.
|
||||
/// </summary>
|
||||
public async Task<ГисДоговор[]> ПолучитьДоговорыРСО(
|
||||
string номерДоговора, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodExportSupplyResourceContractData(Config);
|
||||
method.EnableMinimalResponseWaitDelay = true;
|
||||
return await method.QueryByContractNumber(номерДоговора, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение списка договоров ресурсоснабжения
|
||||
/// </summary>
|
||||
public async Task<int> ПолучитьДоговорыРСО(
|
||||
Action<ГисДоговор> resultHandler, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodExportSupplyResourceContractData(Config);
|
||||
return await method.QueryAll(resultHandler, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Запрос на экспорт объектов жилищного фонда из договора ресурсоснабжения
|
||||
/// </summary>
|
||||
public async Task<int> ПолучитьАдресаДоговораРСО(
|
||||
ГисДоговор договор, Action<ГисАдресныйОбъект> resultHandler, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodExportSupplyResourceContractObjectAddress(Config);
|
||||
return await method.QueryAddresses(договор, resultHandler, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Размещение изменения списка адресных объектов в договоре
|
||||
/// </summary>
|
||||
public async Task РазместитьАдресаДоговораРСО(
|
||||
ГисДоговор договор,
|
||||
IEnumerable<ГисАдресныйОбъект> адресаДляРазмещения,
|
||||
IEnumerable<ГисАдресныйОбъект> адресаДляУдаления,
|
||||
CancellationToken token)
|
||||
{
|
||||
var method = new HcsMethodImportSupplyResourceContractObjectAddress(Config);
|
||||
await method.ImportObjectAddresses(договор, адресаДляРазмещения, адресаДляУдаления, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение списка лицевых счетов для одного здания
|
||||
/// </summary>
|
||||
public async Task<int> ПолучитьЛицевыеСчетаПоЗданию(
|
||||
Guid fiasHouseGuid, Action<ГисЛицевойСчет> resultHandler, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodExportAccountData(Config);
|
||||
return await method.Query(fiasHouseGuid, null, resultHandler, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение списка приборов учета для одного здания
|
||||
/// </summary>
|
||||
public async Task<int> ПолучитьПриборыУчетаПоЗданию(
|
||||
Guid fiasHouseGuid, Action<ГисПриборУчета> resultHandler, CancellationToken token = default)
|
||||
{
|
||||
var method = new HcsMethodExportMeteringDeviceData(Config);
|
||||
return await method.ExportByHouse(fiasHouseGuid, resultHandler, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пример получения данных об одном здании по его идентификатору в ФИАС
|
||||
/// </summary>
|
||||
public async Task<ГисЗдание> ПолучитьЗданиеПоГуидФиас(Guid fiasHouseGuid, CancellationToken token = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var method = new HcsMethodExportHouse(Config);
|
||||
return await method.ExportHouseByFiasGuid(fiasHouseGuid, token);
|
||||
}
|
||||
catch (HcsException e)
|
||||
{
|
||||
throw new HcsException($"Не удалось получить здание по ФИАС GUID {fiasHouseGuid}", e);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ГисДоговорыИПриборы> ПолучитьВсеДоговорыИПриборы(
|
||||
Func<ГисДоговор, bool> contractFilter, CancellationToken token = default)
|
||||
{
|
||||
return await (new HcsContractRegistryDownloader(this))
|
||||
.ПолучитьВсеДоговорыИПриборы(contractFilter, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,162 @@
|
||||
using Hcs.ClientApi.RemoteCaller;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HouseManagement = Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
|
||||
namespace Hcs.Service.Async.HouseManagement.v14_5_0_1
|
||||
{
|
||||
public partial class AckRequestAck : IHcsAck { }
|
||||
public partial class getStateResult : IHcsGetStateResult { }
|
||||
public partial class Fault : IHcsFault { }
|
||||
public partial class HeaderType : IHcsHeaderType { }
|
||||
}
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
public class HcsHouseManagementMethod : HcsRemoteCallMethod
|
||||
{
|
||||
public HcsEndPoints EndPoint => HcsEndPoints.HomeManagementAsync;
|
||||
|
||||
public HouseManagement.RequestHeader CreateRequestHeader() =>
|
||||
HcsRequestHelper.CreateHeader<HouseManagement.RequestHeader>(ClientConfig);
|
||||
|
||||
public HcsHouseManagementMethod(HcsClientConfig config) : base(config) { }
|
||||
|
||||
public System.ServiceModel.EndpointAddress RemoteAddress
|
||||
=> GetEndpointAddress(HcsConstants.EndPointLocator.GetPath(EndPoint));
|
||||
|
||||
private HouseManagement.HouseManagementPortsTypeAsyncClient NewPortClient()
|
||||
{
|
||||
var client = new HouseManagement.HouseManagementPortsTypeAsyncClient(_binding, RemoteAddress);
|
||||
ConfigureEndpointCredentials(client.Endpoint, client.ClientCredentials);
|
||||
return client;
|
||||
}
|
||||
|
||||
public async Task<IHcsGetStateResult> SendAndWaitResultAsync(
|
||||
object request,
|
||||
Func<HouseManagement.HouseManagementPortsTypeAsyncClient, Task<IHcsAck>> sender,
|
||||
CancellationToken token)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
try
|
||||
{
|
||||
if (CanBeRestarted)
|
||||
{
|
||||
return await RunRepeatableTaskInsistentlyAsync(
|
||||
async () => await SendAndWaitResultAsyncImpl(request, sender, token), token);
|
||||
}
|
||||
else
|
||||
{
|
||||
return await SendAndWaitResultAsyncImpl(request, sender, token);
|
||||
}
|
||||
}
|
||||
catch (HcsRestartTimeoutException e)
|
||||
{
|
||||
if (!CanBeRestarted) throw new HcsException("Превышен лимит ожидания выполнения запроса", e);
|
||||
Log($"Перезапускаем запрос типа {request.GetType().Name}...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<IHcsGetStateResult> SendAndWaitResultAsyncImpl(
|
||||
object request,
|
||||
Func<HouseManagement.HouseManagementPortsTypeAsyncClient, Task<IHcsAck>> sender,
|
||||
CancellationToken token)
|
||||
{
|
||||
if (request == null) throw new ArgumentNullException(nameof(request));
|
||||
string version = HcsRequestHelper.GetRequestVersionString(request);
|
||||
_config.Log($"Отправляем запрос: {RemoteAddress.Uri}/{request.GetType().Name} в версии {version}...");
|
||||
|
||||
var stopWatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
||||
IHcsAck ack;
|
||||
using (var client = NewPortClient())
|
||||
{
|
||||
ack = await sender(client);
|
||||
}
|
||||
|
||||
stopWatch.Stop();
|
||||
_config.Log($"Запрос принят в обработку за {stopWatch.ElapsedMilliseconds}мс., подтверждение {ack.MessageGUID}");
|
||||
|
||||
var stateResult = await WaitForResultAsync(ack, true, token);
|
||||
|
||||
stateResult.Items.OfType<HouseManagement.ErrorMessageType>().ToList().ForEach(x =>
|
||||
{
|
||||
throw HcsRemoteException.CreateNew(x.ErrorCode, x.Description);
|
||||
});
|
||||
|
||||
return stateResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Выполняет однократную проверку наличия результата.
|
||||
/// Возвращает null если результата еще нет.
|
||||
/// </summary>
|
||||
protected override async Task<IHcsGetStateResult> TryGetResultAsync(IHcsAck sourceAck, CancellationToken token)
|
||||
{
|
||||
using (var client = NewPortClient())
|
||||
{
|
||||
var requestHeader = HcsRequestHelper.CreateHeader<HouseManagement.RequestHeader>(_config);
|
||||
var requestBody = new HouseManagement.getStateRequest { MessageGUID = sourceAck.MessageGUID };
|
||||
|
||||
var response = await client.getStateAsync(requestHeader, requestBody);
|
||||
var resultBody = response.getStateResult;
|
||||
|
||||
if (resultBody.RequestState == HcsAsyncRequestStateTypes.Ready)
|
||||
{
|
||||
return resultBody;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Разбирает стандартный ответ HCS на операцию импорта с приемом ошибок
|
||||
/// </summary>
|
||||
protected HouseManagement.getStateResultImportResultCommonResult ParseSingleImportResult(IHcsGetStateResult stateResult)
|
||||
{
|
||||
return ParseImportResults(stateResult, 1, true).First();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Разбирает стандартный ответ HCS на операцию импорта с приемом ошибок
|
||||
/// </summary>
|
||||
protected HouseManagement.getStateResultImportResultCommonResult[] ParseImportResults(
|
||||
IHcsGetStateResult stateResult, int commonResultRequiredCount, bool checkItemErrors)
|
||||
{
|
||||
var importResult = RequireSingleItem<HouseManagement.getStateResultImportResult>(stateResult.Items);
|
||||
if (IsArrayEmpty(importResult.Items)) throw new HcsException("Пустой ImportResult.Items");
|
||||
importResult.Items.OfType<HouseManagement.ErrorMessageType>().ToList()
|
||||
.ForEach(error => { throw HcsRemoteException.CreateNew(error.ErrorCode, error.Description); });
|
||||
|
||||
var commonResults = importResult.Items.OfType<HouseManagement.getStateResultImportResultCommonResult>();
|
||||
|
||||
foreach (var commonResult in commonResults)
|
||||
{
|
||||
if (IsArrayEmpty(commonResult.Items)) throw new HcsException("Пустой CommonResult.Items");
|
||||
if (checkItemErrors) CheckCommonResultErrors(commonResult);
|
||||
}
|
||||
|
||||
if (commonResults.Count() != commonResultRequiredCount)
|
||||
{
|
||||
throw new HcsException(
|
||||
$"Число результатов {commonResults.Count()} типа CommonResult не равно {commonResultRequiredCount}");
|
||||
}
|
||||
|
||||
return commonResults.ToArray();
|
||||
}
|
||||
|
||||
protected void CheckCommonResultErrors(HouseManagement.getStateResultImportResultCommonResult commonResult)
|
||||
{
|
||||
commonResult.Items.OfType<HouseManagement.CommonResultTypeError>().ToList()
|
||||
.ForEach(error => { throw HcsRemoteException.CreateNew(error.ErrorCode, error.Description); });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
using HouseManagement = Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Методы и константы для работы с номенклатурно-справочной информацией (НСИ)
|
||||
/// применяемой в сервисе hcs-house-management
|
||||
/// https://my.dom.gosuslugi.ru/#!/open-data
|
||||
/// </summary>
|
||||
public class HcsHouseManagementNsi
|
||||
{
|
||||
// Ссылка на НСИ "54 Причина расторжения договора" (реестровый номер 54)
|
||||
// https://my.dom.gosuslugi.ru/#!/open-data-passport?passportName=7710474375-nsi-54
|
||||
public class ПричинаРасторженияДоговора
|
||||
{
|
||||
public static HouseManagement.nsiRef ПоВзаимномуСогласиюСторон => new HouseManagement.nsiRef()
|
||||
{
|
||||
Name = "По взаимному согласию сторон",
|
||||
Code = "4",
|
||||
GUID = "4a481322-05c9-47cb-9d05-30387dff1f93"
|
||||
};
|
||||
}
|
||||
|
||||
// Ссылка на НСИ "22 Причина закрытия лицевого счета" (реестровый номер 22)
|
||||
// https://dom.gosuslugi.ru/opendataapi/nsi-22/v1
|
||||
public class ПричинаЗакрытияЛицевогоСчета
|
||||
{
|
||||
public static HouseManagement.nsiRef РасторжениеДоговора => new HouseManagement.nsiRef()
|
||||
{
|
||||
Name = "Расторжение договора",
|
||||
Code = "11",
|
||||
GUID = "7ee8b4db-dabc-40eb-9009-f4f80b36bfe5"
|
||||
};
|
||||
}
|
||||
|
||||
// Ссылка на НСИ "Причина архивации прибора учета" (реестровый номер 21)
|
||||
// https://my.dom.gosuslugi.ru/#!/open-data-passport?passportName=7710474375-nsi-21
|
||||
public class ПричинаАрхивацииПрибораУчета
|
||||
{
|
||||
public static HouseManagement.nsiRef ИстекСрокЭксплуатации => new HouseManagement.nsiRef()
|
||||
{
|
||||
Code = "12",
|
||||
GUID = "2b8f44f9-7ca1-44f5-803a-af80d6912f36",
|
||||
Name = "Истек срок эксплуатации прибора учета"
|
||||
};
|
||||
|
||||
public static HouseManagement.nsiRef Ошибка => new HouseManagement.nsiRef()
|
||||
{
|
||||
Code = "4",
|
||||
GUID = "d723696f-5ed7-4923-ad6a-9c2c5bce5032",
|
||||
Name = "Ошибка"
|
||||
};
|
||||
}
|
||||
|
||||
// Ссылка на НСИ "Основание заключения договора" (реестровый номер 58)
|
||||
// https://my.dom.gosuslugi.ru/#!/open-data-passport?passportName=7710474375-nsi-58
|
||||
public class ОснованиеЗаключенияДоговора
|
||||
{
|
||||
public static HouseManagement.nsiRef ЗаявлениеПотребителя => new HouseManagement.nsiRef()
|
||||
{
|
||||
Code = "7",
|
||||
GUID = "93cd9d85-91b8-4bf9-ae48-c5f1e691949f",
|
||||
Name = "Заявление потребителя"
|
||||
};
|
||||
|
||||
public static HouseManagement.nsiRef ДоговорУправления => new HouseManagement.nsiRef()
|
||||
{
|
||||
Code = "3",
|
||||
GUID = "11efe618-79f8-4f53-bfd6-11620e8e9e1e",
|
||||
Name = "Договор управления"
|
||||
};
|
||||
}
|
||||
|
||||
public static HouseManagement.ContractSubjectTypeServiceType ElectricSupplyServiceType
|
||||
=> new HouseManagement.ContractSubjectTypeServiceType()
|
||||
{
|
||||
Code = "4",
|
||||
GUID = "903c7763-73f8-4af2-9ec2-94ee08c7beaa",
|
||||
Name = "Электроснабжение"
|
||||
};
|
||||
|
||||
public static HouseManagement.ContractSubjectTypeMunicipalResource ElectricSupplyMunicipalResource
|
||||
=> new HouseManagement.ContractSubjectTypeMunicipalResource()
|
||||
{
|
||||
Code = "8",
|
||||
GUID = "7379be86-6c95-4e41-b000-3bc703d35969",
|
||||
Name = "Электрическая энергия"
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,190 @@
|
||||
using Hcs.ClientApi.DataTypes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HouseManagement = Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Метод получения реестра лицевых счетов
|
||||
/// </summary>
|
||||
public class HcsMethodExportAccountData : HcsHouseManagementMethod
|
||||
{
|
||||
public HcsMethodExportAccountData(HcsClientConfig config) : base(config)
|
||||
{
|
||||
CanBeRestarted = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получает реестр лицевых счетов по зданию с данным ГУИД ФИАС или по списку номеров ЕЛС
|
||||
/// </summary>
|
||||
public async Task<int> Query(
|
||||
Guid? fiasHouseGuid, IEnumerable<string> unifiedAccountNumbers,
|
||||
Action<ГисЛицевойСчет> resultHandler, CancellationToken token)
|
||||
{
|
||||
int numResults = 0;
|
||||
|
||||
var itemNames = new List<HouseManagement.ItemsChoiceType18> { };
|
||||
List<string> items = new List<string> { };
|
||||
|
||||
if (fiasHouseGuid != null)
|
||||
{
|
||||
itemNames.Add(HouseManagement.ItemsChoiceType18.FIASHouseGuid);
|
||||
items.Add(FormatGuid(fiasHouseGuid));
|
||||
}
|
||||
|
||||
if (unifiedAccountNumbers != null)
|
||||
{
|
||||
if (unifiedAccountNumbers.Count() > 1000)
|
||||
throw new HcsException($"Слишком много ЕЛС в запросе {unifiedAccountNumbers.Count()} > допустимых 1000");
|
||||
foreach (var un in unifiedAccountNumbers)
|
||||
{
|
||||
itemNames.Add(HouseManagement.ItemsChoiceType18.UnifiedAccountNumber);
|
||||
items.Add(un);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var request = new HouseManagement.exportAccountRequest
|
||||
{
|
||||
Id = HcsConstants.SignedXmlElementId,
|
||||
Items = items.ToArray(),
|
||||
ItemsElementName = itemNames.ToArray()
|
||||
};
|
||||
|
||||
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
|
||||
{
|
||||
var ackResponse = await portClient.exportAccountDataAsync(
|
||||
CreateRequestHeader(), request);
|
||||
return ackResponse.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
stateResult.Items.OfType<HouseManagement.exportAccountResultType>().ToList().ForEach(
|
||||
account => { resultHandler(Adopt(account)); numResults += 1; });
|
||||
}
|
||||
catch (HcsNoResultsRemoteException)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return numResults;
|
||||
}
|
||||
|
||||
private ГисЛицевойСчет Adopt(HouseManagement.exportAccountResultType source)
|
||||
{
|
||||
return new ГисЛицевойСчет()
|
||||
{
|
||||
ГуидЛицевогоСчета = ParseGuid(source.AccountGUID),
|
||||
НомерЕЛС = source.UnifiedAccountNumber,
|
||||
НомерЛицевогоСчета = source.AccountNumber,
|
||||
ПолнаяПлощадь = (source.TotalSquareSpecified ? (decimal?)source.TotalSquare : null),
|
||||
ЖилаяПлощадь = (source.ResidentialSquareSpecified ? (decimal?)source.ResidentialSquare : null),
|
||||
КодЖКУ = source.ServiceID,
|
||||
ДатаСоздания = (source.CreationDateSpecified ? (DateTime?)source.CreationDate : null),
|
||||
ДатаЗакрытия = (source.Closed != null ? (DateTime?)source.Closed.CloseDate : null),
|
||||
КодНсиПричиныЗакрытия = (source.Closed != null ? source.Closed.CloseReason.Code : null),
|
||||
ИмяПричиныЗакрытия = (source.Closed != null ? source.Closed.Description : null),
|
||||
Размещения = Adopt(source.Accommodation),
|
||||
Основания = Adopt(source.AccountReasons)
|
||||
};
|
||||
}
|
||||
|
||||
private ГисОснованиеЛС[] Adopt(HouseManagement.exportAccountResultTypeAccountReasons source)
|
||||
{
|
||||
if (source == null) throw new ArgumentNullException("HouseManagement.exportAccountResultTypeAccountReasons");
|
||||
|
||||
var основания = new List<ГисОснованиеЛС>();
|
||||
|
||||
if (source.SupplyResourceContract != null)
|
||||
{
|
||||
foreach (var sr in source.SupplyResourceContract)
|
||||
{
|
||||
var основание = new ГисОснованиеЛС();
|
||||
основание.ТипОснованияЛС = ГисТипОснованияЛС.ДоговорРСО;
|
||||
|
||||
for (int i = 0; i < sr.Items.Length; i++)
|
||||
{
|
||||
switch (sr.ItemsElementName[i])
|
||||
{
|
||||
case HouseManagement.ItemsChoiceType9.ContractGUID:
|
||||
основание.ГуидДоговора = ParseGuid(sr.Items[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (основание.ГуидДоговора == default(Guid))
|
||||
throw new HcsException("Для основания ЛС не указан ГУИД договора РСО");
|
||||
|
||||
основания.Add(основание);
|
||||
}
|
||||
}
|
||||
|
||||
if (source.SocialHireContract != null)
|
||||
{
|
||||
var sh = source.SocialHireContract;
|
||||
|
||||
var основание = new ГисОснованиеЛС();
|
||||
основание.ТипОснованияЛС = ГисТипОснованияЛС.Соцнайм;
|
||||
|
||||
for (int i = 0; i < sh.Items.Length; i++)
|
||||
{
|
||||
object itemValue = sh.Items[i];
|
||||
switch (sh.ItemsElementName[i])
|
||||
{
|
||||
case HouseManagement.ItemsChoiceType10.ContractGUID:
|
||||
основание.ГуидДоговора = ParseGuid(itemValue);
|
||||
break;
|
||||
case HouseManagement.ItemsChoiceType10.ContractNumber:
|
||||
основание.НомерДоговора = (itemValue != null ? itemValue.ToString() : null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (основание.ГуидДоговора == default(Guid))
|
||||
throw new HcsException("Для основания ЛС не указан ГУИД договора соцнайма");
|
||||
|
||||
основания.Add(основание);
|
||||
}
|
||||
|
||||
if (source.Contract != null)
|
||||
{
|
||||
var основание = new ГисОснованиеЛС();
|
||||
основание.ТипОснованияЛС = ГисТипОснованияЛС.Договор;
|
||||
основание.ГуидДоговора = ParseGuid(source.Contract.ContractGUID);
|
||||
основания.Add(основание);
|
||||
}
|
||||
|
||||
// TODO: Проверить комментарий
|
||||
// Непонятно что делать с остальными типам основания и даже следует ли их
|
||||
// расшифровывать или считать ошибкой пустого списка оснований
|
||||
return основания.ToArray();
|
||||
}
|
||||
|
||||
private ГисРазмещениеЛС[] Adopt(HouseManagement.AccountExportTypeAccommodation[] array)
|
||||
{
|
||||
if (array == null) throw new ArgumentNullException("HouseManagement.AccountExportTypeAccommodation");
|
||||
return array.ToList().Select(x => Adopt(x)).ToArray();
|
||||
}
|
||||
|
||||
private ГисРазмещениеЛС Adopt(HouseManagement.AccountExportTypeAccommodation source)
|
||||
{
|
||||
var размещение = new ГисРазмещениеЛС();
|
||||
размещение.ПроцентДоли = (source.SharePercentSpecified ? (decimal?)source.SharePercent : null);
|
||||
|
||||
switch (source.ItemElementName)
|
||||
{
|
||||
case HouseManagement.ItemChoiceType7.FIASHouseGuid: размещение.ГуидЗдания = ParseGuid(source.Item); break;
|
||||
case HouseManagement.ItemChoiceType7.PremisesGUID: размещение.ГуидПомещения = ParseGuid(source.Item); break;
|
||||
case HouseManagement.ItemChoiceType7.LivingRoomGUID: размещение.ГуидЖилойКомнаты = ParseGuid(source.Item); break;
|
||||
default: throw new HcsException("Неизвестный тип размещения ЛС: " + source.ItemElementName);
|
||||
}
|
||||
|
||||
return размещение;
|
||||
}
|
||||
}
|
||||
}
|
||||
101
Hcs.Client/ClientApi/HouseManagementApi/HcsMethodExportHouse.cs
Normal file
101
Hcs.Client/ClientApi/HouseManagementApi/HcsMethodExportHouse.cs
Normal file
@ -0,0 +1,101 @@
|
||||
using Hcs.ClientApi.DataTypes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HouseManagement = Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Метод получения информации о доме и его помещениях
|
||||
/// </summary>
|
||||
public class HcsMethodExportHouse : HcsHouseManagementMethod
|
||||
{
|
||||
public HcsMethodExportHouse(HcsClientConfig config) : base(config)
|
||||
{
|
||||
CanBeRestarted = true;
|
||||
}
|
||||
|
||||
public async Task<ГисЗдание> ExportHouseByFiasGuid(Guid fiasHouseGuid, CancellationToken token)
|
||||
{
|
||||
var request = new HouseManagement.exportHouseRequest
|
||||
{
|
||||
Id = HcsConstants.SignedXmlElementId,
|
||||
FIASHouseGuid = FormatGuid(fiasHouseGuid),
|
||||
// TODO: Тут хардкод версии
|
||||
version = "12.2.0.1"
|
||||
};
|
||||
|
||||
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
|
||||
{
|
||||
var response = await portClient.exportHouseDataAsync(CreateRequestHeader(), request);
|
||||
return response.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
return Adopt(RequireSingleItem<HouseManagement.exportHouseResultType>(stateResult.Items));
|
||||
}
|
||||
|
||||
private ГисЗдание Adopt(HouseManagement.exportHouseResultType source)
|
||||
{
|
||||
bool заполнен = false;
|
||||
|
||||
var дом = new ГисЗдание();
|
||||
дом.НомерДомаГис = source.HouseUniqueNumber;
|
||||
var помещения = new List<ГисПомещение>();
|
||||
|
||||
var apartmentHouse = source.Item as HouseManagement.exportHouseResultTypeApartmentHouse;
|
||||
if (apartmentHouse != null)
|
||||
{
|
||||
дом.ТипДома = ГисТипДома.Многоквартирный;
|
||||
дом.ГуидЗданияФиас = ParseGuid(apartmentHouse.BasicCharacteristicts.FIASHouseGuid);
|
||||
if (apartmentHouse.ResidentialPremises != null)
|
||||
{
|
||||
apartmentHouse.ResidentialPremises.ToList().ForEach(x => помещения.Add(Adopt(x)));
|
||||
}
|
||||
if (apartmentHouse.NonResidentialPremises != null)
|
||||
{
|
||||
apartmentHouse.NonResidentialPremises.ToList().ForEach(x => помещения.Add(Adopt(x)));
|
||||
}
|
||||
заполнен = true;
|
||||
}
|
||||
|
||||
var livingHouse = source.Item as HouseManagement.exportHouseResultTypeLivingHouse;
|
||||
if (livingHouse != null)
|
||||
{
|
||||
дом.ТипДома = ГисТипДома.Жилой;
|
||||
дом.ГуидЗданияФиас = ParseGuid(livingHouse.BasicCharacteristicts.FIASHouseGuid);
|
||||
заполнен = true;
|
||||
}
|
||||
|
||||
if (!заполнен) throw new HcsException("В информации о доме неизвестный тип данных: " + source.Item);
|
||||
|
||||
дом.Помещения = помещения.ToArray();
|
||||
return дом;
|
||||
}
|
||||
|
||||
private ГисПомещение Adopt(HouseManagement.exportHouseResultTypeApartmentHouseResidentialPremises source)
|
||||
{
|
||||
return new ГисПомещение()
|
||||
{
|
||||
ЭтоЖилоеПомещение = true,
|
||||
НомерПомещения = source.PremisesNum,
|
||||
ГуидПомещения = ParseGuid(source.PremisesGUID),
|
||||
ДатаПрекращения = source.TerminationDateSpecified ? source.TerminationDate : null,
|
||||
Аннулирование = source.AnnulmentInfo
|
||||
};
|
||||
}
|
||||
|
||||
private ГисПомещение Adopt(HouseManagement.exportHouseResultTypeApartmentHouseNonResidentialPremises source)
|
||||
{
|
||||
return new ГисПомещение()
|
||||
{
|
||||
ЭтоЖилоеПомещение = false,
|
||||
НомерПомещения = source.PremisesNum,
|
||||
ГуидПомещения = ParseGuid(source.PremisesGUID)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,165 @@
|
||||
using Hcs.ClientApi.DataTypes;
|
||||
using Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HouseManagement = Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Метод получения списка приборов учета
|
||||
/// </summary>
|
||||
public class HcsMethodExportMeteringDeviceData : HcsHouseManagementMethod
|
||||
{
|
||||
public HcsMethodExportMeteringDeviceData(HcsClientConfig config) : base(config)
|
||||
{
|
||||
CanBeRestarted = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение списка приборов учета для одного здания
|
||||
/// </summary>
|
||||
public async Task<int> ExportByHouse(
|
||||
Guid fiasHouseGuid, Action<ГисПриборУчета> resultHandler, CancellationToken token)
|
||||
{
|
||||
List<HouseManagement.ItemsChoiceType4> itemNames = [HouseManagement.ItemsChoiceType4.FIASHouseGuid];
|
||||
List<string> items = [FormatGuid(fiasHouseGuid)];
|
||||
|
||||
var request = new HouseManagement.exportMeteringDeviceDataRequest
|
||||
{
|
||||
Id = HcsConstants.SignedXmlElementId,
|
||||
Items = items.ToArray(),
|
||||
ItemsElementName = itemNames.ToArray(),
|
||||
// TODO: Проверить комментарий
|
||||
//version = "11.1.0.2" // Версия указана в API
|
||||
};
|
||||
|
||||
int numResults = 0;
|
||||
try
|
||||
{
|
||||
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
|
||||
{
|
||||
var ackResponse = await portClient.exportMeteringDeviceDataAsync(CreateRequestHeader(), request);
|
||||
return ackResponse.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
stateResult.Items.OfType<HouseManagement.exportMeteringDeviceDataResultType>().ToList().ForEach(
|
||||
device => { resultHandler(Adopt(device)); numResults += 1; }
|
||||
);
|
||||
}
|
||||
catch (HcsNoResultsRemoteException)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return numResults;
|
||||
}
|
||||
|
||||
private ГисПриборУчета Adopt(HouseManagement.exportMeteringDeviceDataResultType source)
|
||||
{
|
||||
var прибор = new ГисПриборУчета()
|
||||
{
|
||||
ГуидПрибораУчета = ParseGuid(source.MeteringDeviceRootGUID),
|
||||
ГуидВерсииПрибора = ParseGuid(source.MeteringDeviceVersionGUID),
|
||||
НомерПрибораУчетаГис = source.MeteringDeviceGISGKHNumber,
|
||||
ЗаводскойНомер = source.BasicChatacteristicts.MeteringDeviceNumber,
|
||||
МодельПрибораУчета = source.BasicChatacteristicts.MeteringDeviceModel,
|
||||
ДатаРазмещенияВерсии = source.UpdateDateTime
|
||||
};
|
||||
|
||||
if (!IsArrayEmpty(source.MeteringOwner))
|
||||
{
|
||||
прибор.ГуидВладельцаПрибора = ParseGuid(source.MeteringOwner[0]);
|
||||
}
|
||||
|
||||
switch (source.StatusRootDoc)
|
||||
{
|
||||
case HouseManagement.exportMeteringDeviceDataResultTypeStatusRootDoc.Active:
|
||||
прибор.СтатусПрибораУчета = ГисСтатусПрибораУчета.Активный;
|
||||
break;
|
||||
case HouseManagement.exportMeteringDeviceDataResultTypeStatusRootDoc.Archival:
|
||||
прибор.СтатусПрибораУчета = ГисСтатусПрибораУчета.Архивный;
|
||||
break;
|
||||
default:
|
||||
throw new HcsException($"Неизвестный статус ПУ {source.StatusRootDoc} для №{прибор.ЗаводскойНомер}");
|
||||
}
|
||||
|
||||
var basic = source.BasicChatacteristicts;
|
||||
|
||||
прибор.ДатаУстановки = basic.InstallationDateSpecified ? basic.InstallationDate : null;
|
||||
прибор.ДатаВводаВЭксплуатацию = basic.CommissioningDateSpecified ? basic.CommissioningDate : null;
|
||||
прибор.ДатаПоследнейПоверки = basic.FirstVerificationDateSpecified ? basic.FirstVerificationDate : null;
|
||||
прибор.ДатаИзготовления = basic.FactorySealDateSpecified ? basic.FactorySealDate : null;
|
||||
|
||||
прибор.РежимДистанционногоОпроса = basic.RemoteMeteringMode;
|
||||
прибор.ОписаниеДистанционногоОпроса = basic.RemoteMeteringInfo;
|
||||
|
||||
object basicItem = basic.Item;
|
||||
bool типНайден = false;
|
||||
|
||||
CallOnType<HouseManagement.MeteringDeviceBasicCharacteristicsTypeResidentialPremiseDevice>(basicItem, x =>
|
||||
{
|
||||
прибор.ГуидыЛицевыхСчетов = ParseGuidArray(x.AccountGUID);
|
||||
прибор.ГуидыПомещений = ParseGuidArray(x.PremiseGUID);
|
||||
прибор.ВидПрибораУчета = ГисВидПрибораУчета.ЖилоеПомещение;
|
||||
типНайден = true;
|
||||
});
|
||||
|
||||
CallOnType<HouseManagement.MeteringDeviceBasicCharacteristicsTypeNonResidentialPremiseDevice>(basicItem, x =>
|
||||
{
|
||||
прибор.ГуидыЛицевыхСчетов = ParseGuidArray(x.AccountGUID);
|
||||
прибор.ГуидыПомещений = ParseGuidArray(x.PremiseGUID);
|
||||
прибор.ВидПрибораУчета = ГисВидПрибораУчета.НежилоеПомещение;
|
||||
типНайден = true;
|
||||
});
|
||||
|
||||
CallOnType<HouseManagement.MeteringDeviceBasicCharacteristicsTypeCollectiveDevice>(basicItem, x =>
|
||||
{
|
||||
прибор.ГуидыЗданийФиас = ParseGuidArray(x.FIASHouseGuid);
|
||||
прибор.ВидПрибораУчета = ГисВидПрибораУчета.ОДПУ;
|
||||
типНайден = true;
|
||||
});
|
||||
|
||||
CallOnType<HouseManagement.MeteringDeviceBasicCharacteristicsTypeCollectiveApartmentDevice>(basicItem, x =>
|
||||
{
|
||||
прибор.ГуидыЛицевыхСчетов = ParseGuidArray(x.AccountGUID);
|
||||
прибор.ГуидыПомещений = ParseGuidArray(x.PremiseGUID);
|
||||
прибор.ВидПрибораУчета = ГисВидПрибораУчета.КоммунальнаяКвартира;
|
||||
типНайден = true;
|
||||
});
|
||||
|
||||
CallOnType<HouseManagement.MeteringDeviceBasicCharacteristicsTypeLivingRoomDevice>(basicItem, x =>
|
||||
{
|
||||
прибор.ГуидыЛицевыхСчетов = ParseGuidArray(x.AccountGUID);
|
||||
прибор.ГуидыЖилыхКомнат = ParseGuidArray(x.LivingRoomGUID);
|
||||
прибор.ВидПрибораУчета = ГисВидПрибораУчета.ЖилаяКомната;
|
||||
типНайден = true;
|
||||
});
|
||||
|
||||
CallOnType<HouseManagement.MeteringDeviceBasicCharacteristicsTypeApartmentHouseDevice>(basicItem, x =>
|
||||
{
|
||||
прибор.ГуидыЗданийФиас = ParseGuidArray(x.FIASHouseGuid);
|
||||
прибор.ГуидыЛицевыхСчетов = ParseGuidArray(x.AccountGUID);
|
||||
прибор.ВидПрибораУчета = ГисВидПрибораУчета.ЖилойДом;
|
||||
типНайден = true;
|
||||
});
|
||||
|
||||
if (!типНайден) throw new HcsException($"Неизвестный тип ПУ {basicItem} для №{прибор.ЗаводскойНомер}");
|
||||
|
||||
foreach (var electric in source.Items.OfType<MunicipalResourceElectricExportType>())
|
||||
{
|
||||
прибор.КоэффициентТрансформации =
|
||||
(electric.TransformationRatioSpecified ? electric.TransformationRatio : 0);
|
||||
прибор.ПоказаниеТ1 = electric.MeteringValueT1;
|
||||
прибор.ПоказаниеТ2 = electric.MeteringValueT2;
|
||||
прибор.ПоказаниеТ3 = electric.MeteringValueT3;
|
||||
}
|
||||
|
||||
return прибор;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,297 @@
|
||||
using Hcs.ClientApi.DataTypes;
|
||||
using Hcs.ClientApi.RemoteCaller;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HouseManagement = Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Метод получения реестра договоров ресурсоснабжения (ДРСО)
|
||||
/// </summary>
|
||||
public class HcsMethodExportSupplyResourceContractData : HcsHouseManagementMethod
|
||||
{
|
||||
public HcsMethodExportSupplyResourceContractData(HcsClientConfig config) : base(config)
|
||||
{
|
||||
CanBeRestarted = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получает один договор ресурсоснабжения по его GUID
|
||||
/// </summary>
|
||||
public async Task<ГисДоговор> QueryOne(Guid contractRootGuid, CancellationToken token)
|
||||
{
|
||||
ГисДоговор договор = null;
|
||||
Action<ГисДоговор> handler = (result) => { договор = result; };
|
||||
await QueryOneBatch(contractRootGuid, null, handler, null, token);
|
||||
if (договор == null)
|
||||
throw new HcsNoResultsRemoteException($"Нет договора РСО с ГУИД {contractRootGuid}");
|
||||
return договор;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получает один договор ресурсоснабжения по его номеру договора
|
||||
/// </summary>
|
||||
public async Task<ГисДоговор[]> QueryByContractNumber(string contractNumber, CancellationToken token)
|
||||
{
|
||||
var list = new List<ГисДоговор>();
|
||||
Action<ГисДоговор> handler = list.Add;
|
||||
await QueryOneBatch(null, contractNumber, handler, null, token);
|
||||
if (!list.Any()) throw new HcsNoResultsRemoteException($"Нет договора РСО с номером {contractNumber}");
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получает полный список реестра договоров ресурсоснабжения
|
||||
/// </summary>
|
||||
public async Task<int> QueryAll(Action<ГисДоговор> resultHandler, CancellationToken token)
|
||||
{
|
||||
int numResults = 0;
|
||||
int numPages = 0;
|
||||
|
||||
Action<ГисДоговор> countingHandler = (result) =>
|
||||
{
|
||||
numResults += 1;
|
||||
resultHandler(result);
|
||||
};
|
||||
|
||||
Guid? nextGuid = null;
|
||||
while (true)
|
||||
{
|
||||
if (++numPages > 1) Log($"Запрашиваем страницу #{numPages} данных...");
|
||||
var paged = await QueryOneBatch(null, null, countingHandler, nextGuid, token);
|
||||
if (paged.IsLastPage) break;
|
||||
nextGuid = paged.NextGuid;
|
||||
}
|
||||
|
||||
return numResults;
|
||||
}
|
||||
|
||||
private async Task<HcsPagedResultState> QueryOneBatch(
|
||||
Guid? contractRootGuid, string contractNumber, Action<ГисДоговор> resultHandler,
|
||||
Guid? exportNextGuid, CancellationToken token)
|
||||
{
|
||||
var itemNames = new List<HouseManagement.ItemsChoiceType27> { };
|
||||
List<object> items = new List<object> { };
|
||||
|
||||
if (contractRootGuid != null)
|
||||
{
|
||||
itemNames.Add(HouseManagement.ItemsChoiceType27.ContractRootGUID);
|
||||
items.Add(FormatGuid(contractRootGuid));
|
||||
}
|
||||
|
||||
if (contractNumber != null)
|
||||
{
|
||||
itemNames.Add(HouseManagement.ItemsChoiceType27.ContractNumber);
|
||||
items.Add(contractNumber);
|
||||
}
|
||||
|
||||
if (exportNextGuid != null)
|
||||
{
|
||||
itemNames.Add(HouseManagement.ItemsChoiceType27.ExportContractRootGUID);
|
||||
items.Add(FormatGuid(exportNextGuid));
|
||||
}
|
||||
|
||||
var request = new HouseManagement.exportSupplyResourceContractRequest
|
||||
{
|
||||
Id = HcsConstants.SignedXmlElementId,
|
||||
Items = items.ToArray(),
|
||||
ItemsElementName = itemNames.ToArray(),
|
||||
// TODO: Проверить хардкод версии
|
||||
version = "13.1.1.1" // Значение из сообщения об ошибке от сервера HCS
|
||||
};
|
||||
|
||||
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
|
||||
{
|
||||
var ackResponse = await portClient.exportSupplyResourceContractDataAsync(
|
||||
CreateRequestHeader(), request);
|
||||
return ackResponse.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
var result = RequireSingleItem
|
||||
<HouseManagement.getStateResultExportSupplyResourceContractResult>(stateResult.Items);
|
||||
|
||||
foreach (var c in result.Contract)
|
||||
{
|
||||
resultHandler(Adopt(c));
|
||||
}
|
||||
|
||||
return new HcsPagedResultState(result.Item);
|
||||
}
|
||||
|
||||
private ГисДоговор Adopt(HouseManagement.exportSupplyResourceContractResultType source)
|
||||
{
|
||||
var договор = new ГисДоговор()
|
||||
{
|
||||
ГуидДоговора = ParseGuid(source.ContractRootGUID),
|
||||
ГуидВерсииДоговора = ParseGuid(source.ContractGUID),
|
||||
НомерВерсии = source.VersionNumber,
|
||||
СостояниеДоговора = Adopt(source.ContractState),
|
||||
СтатусВерсииДоговора = Adopt(source.VersionStatus)
|
||||
};
|
||||
|
||||
if (source.Item is HouseManagement.ExportSupplyResourceContractTypeIsContract isContract)
|
||||
{
|
||||
договор.ТипДоговораРСО = ГисТипДоговораРСО.НеПубличныйИлиНеНежилые;
|
||||
договор.НомерДоговора = isContract.ContractNumber;
|
||||
договор.ДатаЗаключения = (DateTime?)isContract.SigningDate;
|
||||
договор.ДатаВступленияВСилу = (DateTime?)isContract.EffectiveDate;
|
||||
if (isContract.ContractAttachment != null)
|
||||
{
|
||||
договор.ПриложенияДоговора = isContract.ContractAttachment.Select(AdoptAttachment).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
if (source.Item is HouseManagement.ExportSupplyResourceContractTypeIsNotContract isNotContract)
|
||||
{
|
||||
договор.ТипДоговораРСО = ГисТипДоговораРСО.ПубличныйИлиНежилые;
|
||||
договор.НомерДоговора = isNotContract.ContractNumber;
|
||||
договор.ДатаЗаключения = isNotContract.SigningDateSpecified ? isNotContract.SigningDate : null;
|
||||
договор.ДатаВступленияВСилу = isNotContract.EffectiveDateSpecified ? isNotContract.EffectiveDate : null;
|
||||
if (isNotContract.ContractAttachment != null)
|
||||
{
|
||||
договор.ПриложенияДоговора = isNotContract.ContractAttachment.Select(AdoptAttachment).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
var предметы = new List<ГисПредметДоговора>();
|
||||
foreach (var subject in source.ContractSubject)
|
||||
{
|
||||
var предмет = new ГисПредметДоговора()
|
||||
{
|
||||
КодНсиУслуги = subject.ServiceType.Code,
|
||||
ГуидНсиУслуги = ParseGuid(subject.ServiceType.GUID),
|
||||
ИмяНсиУслуги = subject.ServiceType.Name,
|
||||
КодНсиРесурса = subject.MunicipalResource.Code,
|
||||
ГуидНсиРесурса = ParseGuid(subject.MunicipalResource.GUID),
|
||||
ИмяНсиРесурса = subject.MunicipalResource.Name
|
||||
};
|
||||
предметы.Add(предмет);
|
||||
}
|
||||
договор.ПредметыДоговора = предметы.ToArray();
|
||||
|
||||
договор.Контрагент = AdoptCounterparty(source.Item1);
|
||||
|
||||
if (source.CountingResourceSpecified)
|
||||
{
|
||||
if (source.CountingResource == HouseManagement.ExportSupplyResourceContractTypeCountingResource.R)
|
||||
договор.НачисленияРазмещаетРСО = true;
|
||||
}
|
||||
|
||||
if (source.MeteringDeviceInformationSpecified)
|
||||
{
|
||||
if (source.MeteringDeviceInformation == true)
|
||||
договор.ПриборыРазмещаетРСО = true;
|
||||
}
|
||||
|
||||
return договор;
|
||||
}
|
||||
|
||||
private ГисПриложение AdoptAttachment(HouseManagement.AttachmentType attachment)
|
||||
{
|
||||
return new ГисПриложение()
|
||||
{
|
||||
ИмяПриложения = attachment.Name,
|
||||
ГуидПриложения = ParseGuid(attachment.Attachment.AttachmentGUID),
|
||||
ХэшПриложения = attachment.AttachmentHASH
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Разбор сведений о контрагенте - второй стороне договора
|
||||
/// </summary>
|
||||
private ГисКонтрагент AdoptCounterparty(object item1)
|
||||
{
|
||||
switch (item1)
|
||||
{
|
||||
case HouseManagement.ExportSupplyResourceContractTypeApartmentBuildingOwner owner:
|
||||
return AdoptCounterpartyEntity(owner.Item, ГисТипКонтрагента.ВладелецПомещения);
|
||||
|
||||
case HouseManagement.ExportSupplyResourceContractTypeApartmentBuildingRepresentativeOwner rep:
|
||||
return AdoptCounterpartyEntity(rep.Item, ГисТипКонтрагента.ВладелецПомещения);
|
||||
|
||||
case HouseManagement.ExportSupplyResourceContractTypeApartmentBuildingSoleOwner sole:
|
||||
return AdoptCounterpartyEntity(sole.Item, ГисТипКонтрагента.ВладелецПомещения);
|
||||
|
||||
case HouseManagement.ExportSupplyResourceContractTypeLivingHouseOwner owner:
|
||||
return AdoptCounterpartyEntity(owner.Item, ГисТипКонтрагента.ВладелецПомещения);
|
||||
|
||||
case HouseManagement.ExportSupplyResourceContractTypeOrganization uk:
|
||||
return new ГисКонтрагент()
|
||||
{
|
||||
ТипКонтрагента = ГисТипКонтрагента.УправляющаяКомпания,
|
||||
ГуидОрганизации = ParseGuid(uk.orgRootEntityGUID)
|
||||
};
|
||||
}
|
||||
|
||||
return new ГисКонтрагент() { ТипКонтрагента = ГисТипКонтрагента.НеУказано };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Разбор ссылки на контрагента - второй стороны договора
|
||||
/// </summary>
|
||||
private ГисКонтрагент AdoptCounterpartyEntity(object item, ГисТипКонтрагента типКонтрагента)
|
||||
{
|
||||
switch (item)
|
||||
{
|
||||
case HouseManagement.DRSORegOrgType org:
|
||||
return new ГисКонтрагент()
|
||||
{
|
||||
ТипКонтрагента = типКонтрагента,
|
||||
ГуидОрганизации = ParseGuid(org.orgRootEntityGUID)
|
||||
};
|
||||
|
||||
case HouseManagement.DRSOIndType ind:
|
||||
var индивид = new ГисИндивид()
|
||||
{
|
||||
Фамилия = ind.Surname,
|
||||
Имя = ind.FirstName,
|
||||
Отчество = ind.Patronymic
|
||||
};
|
||||
|
||||
switch (ind.Item)
|
||||
{
|
||||
case string снилс: индивид.СНИЛС = снилс; break;
|
||||
case HouseManagement.ID id:
|
||||
индивид.НомерДокумента = id.Number;
|
||||
индивид.СерияДокумента = id.Series;
|
||||
индивид.ДатаДокумента = id.IssueDate;
|
||||
break;
|
||||
}
|
||||
|
||||
return new ГисКонтрагент() { ТипКонтрагента = типКонтрагента, Индивид = индивид, };
|
||||
}
|
||||
|
||||
return new ГисКонтрагент() { ТипКонтрагента = ГисТипКонтрагента.НеУказано };
|
||||
}
|
||||
|
||||
internal static ГисСтатусВерсииДоговора Adopt(
|
||||
HouseManagement.exportSupplyResourceContractResultTypeVersionStatus source)
|
||||
{
|
||||
switch (source)
|
||||
{
|
||||
case HouseManagement.exportSupplyResourceContractResultTypeVersionStatus.Posted: return ГисСтатусВерсииДоговора.Размещен;
|
||||
case HouseManagement.exportSupplyResourceContractResultTypeVersionStatus.Terminated: return ГисСтатусВерсииДоговора.Расторгнут;
|
||||
case HouseManagement.exportSupplyResourceContractResultTypeVersionStatus.Draft: return ГисСтатусВерсииДоговора.Проект;
|
||||
case HouseManagement.exportSupplyResourceContractResultTypeVersionStatus.Annul: return ГисСтатусВерсииДоговора.Аннулирован;
|
||||
default: throw NewUnexpectedObjectException(source);
|
||||
}
|
||||
}
|
||||
|
||||
internal static ГисСостояниеДоговора Adopt(
|
||||
HouseManagement.exportSupplyResourceContractResultTypeContractState source)
|
||||
{
|
||||
switch (source)
|
||||
{
|
||||
case HouseManagement.exportSupplyResourceContractResultTypeContractState.Expired: return ГисСостояниеДоговора.ИстекСрокДействия;
|
||||
case HouseManagement.exportSupplyResourceContractResultTypeContractState.NotTakeEffect: return ГисСостояниеДоговора.НеВступилВСилу;
|
||||
case HouseManagement.exportSupplyResourceContractResultTypeContractState.Proceed: return ГисСостояниеДоговора.Действующий;
|
||||
default: throw NewUnexpectedObjectException(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,125 @@
|
||||
using Hcs.ClientApi.DataTypes;
|
||||
using Hcs.ClientApi.RemoteCaller;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HouseManagement = Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Метод получения списка адресных объектов по договору ресурсоснабжения
|
||||
/// </summary>
|
||||
public class HcsMethodExportSupplyResourceContractObjectAddress : HcsHouseManagementMethod
|
||||
{
|
||||
public HcsMethodExportSupplyResourceContractObjectAddress(HcsClientConfig config) : base(config)
|
||||
{
|
||||
EnableMinimalResponseWaitDelay = true;
|
||||
CanBeRestarted = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Запрос на экспорт объектов жилищного фонда из договора ресурсоснабжения
|
||||
/// </summary>
|
||||
public async Task<int> QueryAddresses(
|
||||
ГисДоговор договор, Action<ГисАдресныйОбъект> resultHandler, CancellationToken token)
|
||||
{
|
||||
int numResults = 0;
|
||||
|
||||
Action<ГисАдресныйОбъект> countingHandler = (result) =>
|
||||
{
|
||||
numResults += 1;
|
||||
resultHandler(result);
|
||||
};
|
||||
|
||||
Guid? nextGuid = null;
|
||||
while (true)
|
||||
{
|
||||
var paged = await QueryOneBatch(договор, countingHandler, nextGuid, token);
|
||||
if (paged.IsLastPage) break;
|
||||
nextGuid = paged.NextGuid;
|
||||
numResults += 1;
|
||||
}
|
||||
|
||||
return numResults;
|
||||
}
|
||||
|
||||
private async Task<HcsPagedResultState> QueryOneBatch(
|
||||
ГисДоговор договор, Action<ГисАдресныйОбъект> resultHandler,
|
||||
Guid? firstGuid, CancellationToken token)
|
||||
{
|
||||
var itemNames = new List<HouseManagement.ItemsChoiceType29> { };
|
||||
List<string> items = new List<string> { };
|
||||
|
||||
if (договор.ГуидВерсииДоговора != default)
|
||||
{
|
||||
itemNames.Add(HouseManagement.ItemsChoiceType29.ContractGUID);
|
||||
items.Add(FormatGuid(договор.ГуидВерсииДоговора));
|
||||
}
|
||||
else
|
||||
{
|
||||
itemNames.Add(HouseManagement.ItemsChoiceType29.ContractRootGUID);
|
||||
items.Add(FormatGuid(договор.ГуидДоговора));
|
||||
}
|
||||
|
||||
// TODO: Проверить комментарий
|
||||
// Если указан guid следующей страницы данных, добавляем его в параметры
|
||||
// (на 20.12.2023 эта функция не работает, первый пакет содержит 1000 записей
|
||||
// и запрос второго пакета с ExportObjectGUID возвращает "Bad request")
|
||||
if (firstGuid != null)
|
||||
{
|
||||
itemNames.Add(HouseManagement.ItemsChoiceType29.ExportObjectGUID);
|
||||
items.Add(FormatGuid(firstGuid));
|
||||
}
|
||||
|
||||
var request = new HouseManagement.exportSupplyResourceContractObjectAddressRequest
|
||||
{
|
||||
Id = HcsConstants.SignedXmlElementId,
|
||||
Items = items.ToArray(),
|
||||
ItemsElementName = itemNames.ToArray(),
|
||||
// TODO: Проверить хардкод версии
|
||||
version = "13.1.1.1" // Номер версии из сообщения об ошибке сервера HCS
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
|
||||
{
|
||||
var ackResponse = await portClient.exportSupplyResourceContractObjectAddressDataAsync(
|
||||
CreateRequestHeader(), request);
|
||||
return ackResponse.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
var result = RequireSingleItem
|
||||
<HouseManagement.getStateResultExportSupplyResourceContractObjectAddress>(stateResult.Items);
|
||||
foreach (var x in result.ObjectAddress)
|
||||
{
|
||||
resultHandler(Adopt(x));
|
||||
}
|
||||
|
||||
return new HcsPagedResultState(result.Item);
|
||||
}
|
||||
catch (HcsNoResultsRemoteException)
|
||||
{
|
||||
return HcsPagedResultState.IsLastPageResultState;
|
||||
}
|
||||
}
|
||||
|
||||
private ГисАдресныйОбъект Adopt(
|
||||
HouseManagement.exportSupplyResourceContractObjectAddressResultType source)
|
||||
{
|
||||
return new ГисАдресныйОбъект()
|
||||
{
|
||||
ТипЗдания = (source.HouseTypeSpecified ? source.HouseType.ToString() : null),
|
||||
ГуидЗданияФиас = ParseGuid(source.FIASHouseGuid),
|
||||
ГуидДоговора = ParseGuid(source.ContractRootGUID),
|
||||
ГуидВерсииДоговора = ParseGuid(source.ContractGUID),
|
||||
ГуидАдресногоОбъекта = ParseGuid(source.ObjectGUID),
|
||||
НомерПомещения = source.ApartmentNumber,
|
||||
НомерКомнаты = source.RoomNumber
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,187 @@
|
||||
using Hcs.ClientApi.DataTypes;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HouseManagement = Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Операции размещения и закрытия Лицевых счетов в ГИС ЖКХ
|
||||
/// </summary>
|
||||
public class HcsMethodImportAccountData : HcsHouseManagementMethod
|
||||
{
|
||||
public HcsMethodImportAccountData(HcsClientConfig config) : base(config)
|
||||
{
|
||||
CanBeRestarted = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Размещение нового Лицевого счета если ГисЛицевойСчет.ГуидЛицевогоСчета не заполнен,
|
||||
/// размещение новой версии лицевого счета если заполнен.
|
||||
/// Возвращает Единый номер лицевого счета в ГИС ЖКХ для размещенного ЛС
|
||||
/// http://open-gkh.ru/HouseManagement/importAccountRequest/Account.html
|
||||
/// </summary>
|
||||
public async Task<string> ImportAccount(
|
||||
ГисДоговор договор, ГисЛицевойСчет лицевойСчет, CancellationToken token)
|
||||
{
|
||||
if (лицевойСчет == null) throw new ArgumentNullException(nameof(лицевойСчет));
|
||||
if (договор == null) throw new ArgumentNullException(nameof(договор));
|
||||
|
||||
var account = ConvertToAccount(договор, лицевойСчет);
|
||||
var result = await CallImportAccountData(account, token);
|
||||
return result.UnifiedAccountNumber;
|
||||
}
|
||||
|
||||
private HouseManagement.importAccountRequestAccount ConvertToAccount(
|
||||
ГисДоговор договор, ГисЛицевойСчет лицевойСчет)
|
||||
{
|
||||
var account = new HouseManagement.importAccountRequestAccount()
|
||||
{
|
||||
TransportGUID = FormatGuid(Guid.NewGuid()),
|
||||
AccountNumber = лицевойСчет.НомерЛицевогоСчета
|
||||
};
|
||||
|
||||
if (лицевойСчет.ГуидЛицевогоСчета != default)
|
||||
{
|
||||
account.AccountGUID = FormatGuid(лицевойСчет.ГуидЛицевогоСчета);
|
||||
}
|
||||
|
||||
if (договор.ГуидДоговора == null) throw new HcsException("Не указан ГуидДоговора для размещения ЛС");
|
||||
var reasonRSO = new HouseManagement.AccountReasonsImportTypeSupplyResourceContract()
|
||||
{
|
||||
Items = [FormatGuid(договор.ГуидДоговора)],
|
||||
ItemsElementName = [HouseManagement.ItemsChoiceType9.ContractGUID]
|
||||
};
|
||||
account.AccountReasons = new HouseManagement.AccountReasonsImportType()
|
||||
{
|
||||
SupplyResourceContract = [reasonRSO]
|
||||
};
|
||||
|
||||
account.ItemElementName = HouseManagement.ItemChoiceType18.isRSOAccount;
|
||||
account.Item = true;
|
||||
|
||||
if (IsArrayEmpty(лицевойСчет.Размещения))
|
||||
throw new HcsException($"Не указаны размещения ЛС №{лицевойСчет.НомерЛицевогоСчета}");
|
||||
|
||||
account.Accommodation = лицевойСчет.Размещения.Select(ConvertToAccomodation).ToArray();
|
||||
|
||||
if (лицевойСчет.ДатаЗакрытия != null)
|
||||
{
|
||||
account.Closed = new HouseManagement.ClosedAccountAttributesType()
|
||||
{
|
||||
CloseDate = (DateTime)лицевойСчет.ДатаЗакрытия,
|
||||
CloseReason = HcsHouseManagementNsi.ПричинаЗакрытияЛицевогоСчета.РасторжениеДоговора
|
||||
};
|
||||
}
|
||||
|
||||
account.PayerInfo = new HouseManagement.AccountTypePayerInfo()
|
||||
{
|
||||
Item = ConvertToAccountContragent(договор.Контрагент)
|
||||
};
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
private object ConvertToAccountContragent(ГисКонтрагент контрагент)
|
||||
{
|
||||
if (контрагент == null) throw new HcsException("В договоре не заполнен Контрагент");
|
||||
|
||||
if (контрагент.ГуидОрганизации != null)
|
||||
{
|
||||
if (контрагент.ГуидВерсииОрганизации == null)
|
||||
throw new HcsException("Для размещения ЛС в договоре с ЮЛ обязательно указание ГисКонтрагент.ГуидВерсииОрганизации");
|
||||
|
||||
return new HouseManagement.RegOrgVersionType()
|
||||
{
|
||||
orgVersionGUID = FormatGuid(контрагент.ГуидВерсииОрганизации)
|
||||
};
|
||||
}
|
||||
|
||||
if (контрагент.Индивид != null)
|
||||
{
|
||||
контрагент.Индивид.ПроверитьЗаполнениеСНИЛС();
|
||||
контрагент.Индивид.ПроверитьЗаполнениеФИО();
|
||||
|
||||
return new HouseManagement.AccountIndType()
|
||||
{
|
||||
FirstName = контрагент.Индивид.Имя,
|
||||
Patronymic = контрагент.Индивид.Отчество,
|
||||
Surname = контрагент.Индивид.Фамилия,
|
||||
Item = контрагент.Индивид.СНИЛСТолькоЦифры
|
||||
};
|
||||
}
|
||||
|
||||
throw new HcsException("Не указана ни организация ни индивид для размещения ЛС");
|
||||
}
|
||||
|
||||
private HouseManagement.AccountTypeAccommodation ConvertToAccomodation(ГисРазмещениеЛС размещение)
|
||||
{
|
||||
if (размещение == null) throw new HcsException("Пустое размещение для ЛС");
|
||||
|
||||
var accomodation = new HouseManagement.AccountTypeAccommodation();
|
||||
if (размещение.ГуидПомещения != null)
|
||||
{
|
||||
accomodation.ItemElementName = HouseManagement.ItemChoiceType19.PremisesGUID;
|
||||
accomodation.Item = FormatGuid(размещение.ГуидПомещения);
|
||||
}
|
||||
else if (размещение.ГуидЖилойКомнаты != null)
|
||||
{
|
||||
accomodation.ItemElementName = HouseManagement.ItemChoiceType19.LivingRoomGUID;
|
||||
accomodation.Item = FormatGuid(размещение.ГуидЖилойКомнаты);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new HcsException("Не указан ГУИД помещения или комнаты для ЛС");
|
||||
}
|
||||
|
||||
if (размещение.ПроцентДоли != null)
|
||||
{
|
||||
accomodation.SharePercent = (decimal)размещение.ПроцентДоли;
|
||||
accomodation.SharePercentSpecified = true;
|
||||
}
|
||||
|
||||
return accomodation;
|
||||
}
|
||||
|
||||
private async Task<(string UnifiedAccountNumber, DateTime UpdateDate)> CallImportAccountData(
|
||||
HouseManagement.importAccountRequestAccount account,
|
||||
CancellationToken token)
|
||||
{
|
||||
var request = new HouseManagement.importAccountRequest
|
||||
{
|
||||
Id = HcsConstants.SignedXmlElementId,
|
||||
Account = [account]
|
||||
// TODO: Проверить комментарий
|
||||
//version = "13.1.1.1" // Версия указана в API
|
||||
};
|
||||
|
||||
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
|
||||
{
|
||||
var ackResponse = await portClient.importAccountDataAsync(
|
||||
CreateRequestHeader(), request);
|
||||
return ackResponse.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
var commonResult = ParseSingleImportResult(stateResult);
|
||||
|
||||
switch (commonResult.ItemElementName)
|
||||
{
|
||||
|
||||
case HouseManagement.ItemChoiceType2.ImportAccount:
|
||||
var accountResult = RequireType<HouseManagement.getStateResultImportResultCommonResultImportAccount>(commonResult.Item);
|
||||
|
||||
DateTime updateDate = commonResult.Items.OfType<DateTime>().FirstOrDefault();
|
||||
if (updateDate == default)
|
||||
throw new HcsException("В ответе сервера не указана дата обновления лицевого счета");
|
||||
|
||||
return (accountResult.UnifiedAccountNumber, updateDate);
|
||||
|
||||
default:
|
||||
throw new HcsException($"Неожиданная структура в пакете результата: {commonResult.ItemElementName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,207 @@
|
||||
using Hcs.ClientApi.DataTypes;
|
||||
using Hcs.ClientApi.DeviceMeteringApi;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HouseManagement = Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Метод передачи в ГИС ЖКХ сведений о приборе учета (новом или уже существующем)
|
||||
/// </summary>
|
||||
public class HcsMethodImportMeteringDeviceData : HcsHouseManagementMethod
|
||||
{
|
||||
public HcsMethodImportMeteringDeviceData(HcsClientConfig config) : base(config)
|
||||
{
|
||||
CanBeRestarted = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Размещение нового прибора учета если ГисПриборУчета.ГуидПрибораУчета не заполнен,
|
||||
/// размещение новой версии прибора учета если заполнен.
|
||||
/// Возвращает GUID размещенного прибора учета
|
||||
/// http://open-gkh.ru/HouseManagement/importMeteringDeviceDataRequest.html
|
||||
/// </summary>
|
||||
public async Task<Guid> ImportMeteringDevice(ГисПриборУчета прибор, CancellationToken token)
|
||||
{
|
||||
if (прибор == null) throw new ArgumentNullException(nameof(прибор));
|
||||
|
||||
var device = ConvertToMeteringDevice(прибор);
|
||||
var result = await CallImportMeteringDevice(device, token);
|
||||
return result.MeteringDeviceGuid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Выполняет архивацию(удаление) прибора учета в ГИС.
|
||||
/// В структуре ПриборУчета используется только поле ГуидВерсииПрибора.
|
||||
/// </summary>
|
||||
public async Task<DateTime> ArchiveMeteringDevice(ГисПриборУчета приборУчета, CancellationToken token)
|
||||
{
|
||||
var archive = new HouseManagement.importMeteringDeviceDataRequestMeteringDeviceDeviceDataToUpdateArchiveDevice();
|
||||
archive.ArchivingReason = HcsHouseManagementNsi.ПричинаАрхивацииПрибораУчета.ИстекСрокЭксплуатации;
|
||||
|
||||
var update = new HouseManagement.importMeteringDeviceDataRequestMeteringDeviceDeviceDataToUpdate();
|
||||
update.MeteringDeviceVersionGUID = FormatGuid(приборУчета.ГуидВерсииПрибора);
|
||||
update.Item = archive;
|
||||
|
||||
var device = new HouseManagement.importMeteringDeviceDataRequestMeteringDevice();
|
||||
device.TransportGUID = FormatGuid(Guid.NewGuid());
|
||||
device.Item = update;
|
||||
|
||||
var result = await CallImportMeteringDevice(device, token);
|
||||
return result.UpdateDate;
|
||||
}
|
||||
|
||||
private HouseManagement.importMeteringDeviceDataRequestMeteringDevice
|
||||
ConvertToMeteringDevice(ГисПриборУчета прибор)
|
||||
{
|
||||
var device = new HouseManagement.importMeteringDeviceDataRequestMeteringDevice();
|
||||
|
||||
// ГИС будет возвращать ошибку с указанием этого идентификатора для определения элемента пакета
|
||||
device.TransportGUID = FormatGuid(Guid.NewGuid());
|
||||
|
||||
if (прибор.ГуидВерсииПрибора != default)
|
||||
{
|
||||
var update = new HouseManagement.importMeteringDeviceDataRequestMeteringDeviceDeviceDataToUpdate();
|
||||
update.MeteringDeviceVersionGUID = FormatGuid(прибор.ГуидВерсииПрибора);
|
||||
update.Item = ConvertToFullInformationType(прибор);
|
||||
device.Item = update;
|
||||
}
|
||||
else
|
||||
{
|
||||
device.Item = ConvertToFullInformationType(прибор);
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
private HouseManagement.MeteringDeviceFullInformationType ConvertToFullInformationType(
|
||||
ГисПриборУчета прибор)
|
||||
{
|
||||
var basic = new HouseManagement.MeteringDeviceBasicCharacteristicsType();
|
||||
basic.MeteringDeviceNumber = прибор.ЗаводскойНомер;
|
||||
basic.MeteringDeviceModel = прибор.МодельПрибораУчета;
|
||||
basic.MeteringDeviceStamp = прибор.МодельПрибораУчета;
|
||||
|
||||
basic.TemperatureSensor = false;
|
||||
basic.PressureSensor = false;
|
||||
|
||||
basic.RemoteMeteringMode = прибор.РежимДистанционногоОпроса;
|
||||
if (прибор.РежимДистанционногоОпроса)
|
||||
basic.RemoteMeteringInfo = прибор.ОписаниеДистанционногоОпроса;
|
||||
|
||||
if (прибор.ДатаУстановки != null)
|
||||
{
|
||||
basic.InstallationDate = (DateTime)прибор.ДатаУстановки;
|
||||
basic.InstallationDateSpecified = true;
|
||||
}
|
||||
|
||||
if (прибор.ДатаВводаВЭксплуатацию != null)
|
||||
{
|
||||
basic.CommissioningDate = (DateTime)прибор.ДатаВводаВЭксплуатацию;
|
||||
basic.CommissioningDateSpecified = true;
|
||||
}
|
||||
|
||||
if (прибор.ДатаПоследнейПоверки != null)
|
||||
{
|
||||
basic.FirstVerificationDate = (DateTime)прибор.ДатаПоследнейПоверки;
|
||||
basic.FirstVerificationDateSpecified = true;
|
||||
}
|
||||
|
||||
if (прибор.ДатаИзготовления != null)
|
||||
{
|
||||
basic.FactorySealDate = (DateTime)прибор.ДатаИзготовления;
|
||||
basic.FactorySealDateSpecified = true;
|
||||
}
|
||||
|
||||
switch (прибор.ВидПрибораУчета)
|
||||
{
|
||||
case ГисВидПрибораУчета.ОДПУ:
|
||||
if (IsArrayEmpty(прибор.ГуидыЗданийФиас))
|
||||
throw new HcsException("Для ОДПУ необходимо указать ГУИД здания ФИАС");
|
||||
basic.Item = new HouseManagement.MeteringDeviceBasicCharacteristicsTypeCollectiveDevice()
|
||||
{
|
||||
FIASHouseGuid = прибор.ГуидыЗданийФиас.Select(FormatGuid).ToArray()
|
||||
};
|
||||
break;
|
||||
|
||||
case ГисВидПрибораУчета.НежилоеПомещение:
|
||||
if (IsArrayEmpty(прибор.ГуидыЛицевыхСчетов))
|
||||
throw new HcsException("Для размещения ПУ нежилого помещения следует указать ГУИД лицевого счета");
|
||||
if (IsArrayEmpty(прибор.ГуидыПомещений))
|
||||
throw new HcsException("Для размещения ПУ нежилого помещения следует указать ГУИД помещения");
|
||||
basic.Item = new HouseManagement.MeteringDeviceBasicCharacteristicsTypeNonResidentialPremiseDevice()
|
||||
{
|
||||
AccountGUID = прибор.ГуидыЛицевыхСчетов.Select(FormatGuid).ToArray(),
|
||||
PremiseGUID = прибор.ГуидыПомещений.Select(FormatGuid).ToArray()
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException(
|
||||
"Не реализовано размещение вида прибора: " + прибор.ВидПрибораУчета);
|
||||
}
|
||||
|
||||
var electric = new HouseManagement.MunicipalResourceElectricBaseType();
|
||||
electric.Unit = HouseManagement.MunicipalResourceElectricBaseTypeUnit.Item245; // Константа ОКЕИ 245=кВт*ч
|
||||
electric.UnitSpecified = true;
|
||||
electric.MeteringValueT1 = HcsDeviceMeteringUtil.ConvertMeterReading(прибор.ПоказаниеТ1, true);
|
||||
electric.MeteringValueT2 = HcsDeviceMeteringUtil.ConvertMeterReading(прибор.ПоказаниеТ2, false);
|
||||
electric.MeteringValueT3 = HcsDeviceMeteringUtil.ConvertMeterReading(прибор.ПоказаниеТ3, false);
|
||||
if (прибор.КоэффициентТрансформацииУказан)
|
||||
{
|
||||
electric.TransformationRatio = прибор.КоэффициентТрансформации;
|
||||
electric.TransformationRatioSpecified = true;
|
||||
}
|
||||
|
||||
return new HouseManagement.MeteringDeviceFullInformationType()
|
||||
{
|
||||
BasicChatacteristicts = basic,
|
||||
// TODO: Проверить комментарий
|
||||
Item = true, // NotLinkedWithMetering (нет связей с другими приборами)
|
||||
Items = [electric]
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<(Guid MeteringDeviceGuid, DateTime UpdateDate)> CallImportMeteringDevice(
|
||||
HouseManagement.importMeteringDeviceDataRequestMeteringDevice device,
|
||||
CancellationToken token)
|
||||
{
|
||||
HouseManagement.importMeteringDeviceDataRequestMeteringDevice[] devices = { device };
|
||||
|
||||
var request = new HouseManagement.importMeteringDeviceDataRequest
|
||||
{
|
||||
Id = HcsConstants.SignedXmlElementId,
|
||||
MeteringDevice = devices
|
||||
// TODO: Проверить хардкод версии
|
||||
//version = "13.1.1.1" // Версия указана в API
|
||||
};
|
||||
|
||||
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
|
||||
{
|
||||
var ackResponse = await portClient.importMeteringDeviceDataAsync(
|
||||
CreateRequestHeader(), request);
|
||||
return ackResponse.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
var commonResult = ParseSingleImportResult(stateResult);
|
||||
|
||||
switch (commonResult.ItemElementName)
|
||||
{
|
||||
case HouseManagement.ItemChoiceType2.importMeteringDevice:
|
||||
var deviceResult = RequireType<HouseManagement.getStateResultImportResultCommonResultImportMeteringDevice>(commonResult.Item);
|
||||
|
||||
DateTime updateDate = commonResult.Items.OfType<DateTime>().FirstOrDefault();
|
||||
if (updateDate == default) throw new HcsException("В ответе сервера не указана дата обновления прибора учета");
|
||||
|
||||
return (ParseGuid(deviceResult.MeteringDeviceGUID), updateDate);
|
||||
|
||||
default:
|
||||
throw new HcsException($"Неожиданная структура в пакете результата: {commonResult.ItemElementName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,386 @@
|
||||
using Hcs.ClientApi.DataTypes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HouseManagement = Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Метод передачи в ГИС ЖКХ сведений о договоре РСО (новом или уже существующем)
|
||||
/// </summary>
|
||||
public class HcsMethodImportSupplyResourceContractData : HcsHouseManagementMethod
|
||||
{
|
||||
public HcsMethodImportSupplyResourceContractData(HcsClientConfig config) : base(config)
|
||||
{
|
||||
CanBeRestarted = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Размещение нового договора если ГисДоговор.ГуидДоговора не заполнен,
|
||||
/// размещение новой версии договора если заполнен
|
||||
/// http://open-gkh.ru/HouseManagement/SupplyResourceContractType.html
|
||||
/// </summary>
|
||||
public async Task<DateTime> ImportContract(
|
||||
ГисДоговор договор, IEnumerable<ГисАдресныйОбъект> адреса, CancellationToken token)
|
||||
{
|
||||
if (договор == null) throw new ArgumentNullException(nameof(договор));
|
||||
if (адреса == null || !адреса.Any())
|
||||
throw new ArgumentException($"Для импорта нового договора {договор.НомерДоговора}" +
|
||||
" необходимо указать хотя-бы один адресный объект");
|
||||
|
||||
Guid? contractGuid = (договор.ГуидДоговора == default) ? null : договор.ГуидДоговора;
|
||||
var contract = ConvertToSupplyResourceContract(договор, адреса);
|
||||
return await CallImportContract(contractGuid, contract, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вызывает удаленный метод импорта договора с @contractGuid и данными операции импорта @contractItem.
|
||||
/// Чтобы перевести договор из состояния "Проект" в состояние "Размещен" необходимо вызвать
|
||||
/// importSupplyResourceContractProjectData/PlacingContractProject=true
|
||||
/// http://open-gkh.ru/HouseManagement/importSupplyResourceContractRequest.html
|
||||
/// </summary>
|
||||
private async Task<DateTime> CallImportContract(
|
||||
Guid? contractGuid, object contractItem, CancellationToken token)
|
||||
{
|
||||
var contract = new HouseManagement.importSupplyResourceContractRequestContract();
|
||||
HouseManagement.importSupplyResourceContractRequestContract[] contracts = { contract };
|
||||
|
||||
// Передаем условие запроса - гуид версии договора.
|
||||
// При создании нового договора атрибут importSupplyResourceContractRequest.Contract.ContractGUID не заполняется.
|
||||
if (contractGuid != null)
|
||||
{
|
||||
contract.ItemElementName = HouseManagement.ItemChoiceType26.ContractRootGUID;
|
||||
contract.Item = FormatGuid(contractGuid);
|
||||
}
|
||||
|
||||
contract.TransportGUID = FormatGuid(Guid.NewGuid());
|
||||
|
||||
contract.Item1 = contractItem;
|
||||
|
||||
var request = new HouseManagement.importSupplyResourceContractRequest
|
||||
{
|
||||
Id = HcsConstants.SignedXmlElementId,
|
||||
Contract = contracts
|
||||
// TODO: Проверить комментарий
|
||||
//version = "13.1.1.1" // Версия указана в API
|
||||
};
|
||||
|
||||
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
|
||||
{
|
||||
var ackResponse = await portClient.importSupplyResourceContractDataAsync(
|
||||
CreateRequestHeader(), request);
|
||||
return ackResponse.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
var commonResult = ParseSingleImportResult(stateResult);
|
||||
|
||||
switch (commonResult.ItemElementName)
|
||||
{
|
||||
case HouseManagement.ItemChoiceType2.ImportSupplyResourceContract:
|
||||
var contractResult = RequireType<HouseManagement.getStateResultImportResultCommonResultImportSupplyResourceContract>(commonResult.Item);
|
||||
var датаИмпорта = RequireSingleItem<DateTime>(commonResult.Items);
|
||||
return датаИмпорта;
|
||||
default:
|
||||
throw new HcsException($"Неожиданная структура в пакете результата: {commonResult.ItemElementName}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Преобразует модель данных ГисДоговор в модель данных HouseManagement.SupplyResourceContractType
|
||||
/// http://open-gkh.ru/HouseManagement/SupplyResourceContractType.html
|
||||
/// </summary>
|
||||
private HouseManagement.SupplyResourceContractType ConvertToSupplyResourceContract(
|
||||
ГисДоговор договор, IEnumerable<ГисАдресныйОбъект> адреса)
|
||||
{
|
||||
var contract = new HouseManagement.SupplyResourceContractType();
|
||||
|
||||
if (договор.ЭтоДоговорНежилогоПомещения)
|
||||
{
|
||||
var isNotContract = new HouseManagement.SupplyResourceContractTypeIsNotContract();
|
||||
isNotContract.ContractNumber = договор.НомерДоговора;
|
||||
if (договор.ДатаЗаключения != null)
|
||||
isNotContract.SigningDate = (DateTime)договор.ДатаЗаключения;
|
||||
if (!IsArrayEmpty(договор.ПриложенияДоговора))
|
||||
isNotContract.ContractAttachment = договор.ПриложенияДоговора.Select(ConvertToAttachment).ToArray();
|
||||
contract.Item = isNotContract;
|
||||
}
|
||||
|
||||
if (договор.ЭтоДоговорИКУ)
|
||||
{
|
||||
var isContract = new HouseManagement.SupplyResourceContractTypeIsContract();
|
||||
isContract.ContractNumber = договор.НомерДоговора;
|
||||
var нужнаДатаЗаключения = (договор.ДатаЗаключения != null) ? (DateTime)договор.ДатаЗаключения : DateTime.Now;
|
||||
isContract.SigningDate = isContract.EffectiveDate = нужнаДатаЗаключения;
|
||||
|
||||
// Для ИКУ обязательно приложение файла договора (иначе 400 Bad request)
|
||||
if (IsArrayEmpty(договор.ПриложенияДоговора))
|
||||
throw new HcsException($"Для размещения договора ИКУ {договор.НомерДоговора} необходимо указать файл приложения");
|
||||
isContract.ContractAttachment = договор.ПриложенияДоговора.Select(ConvertToAttachment).ToArray();
|
||||
contract.Item = isContract;
|
||||
}
|
||||
|
||||
if (договор.Контрагент == null)
|
||||
throw new HcsException($"В договоре {договор.НомерДоговора} не указан Контрагент");
|
||||
|
||||
if (договор.ЭтоДоговорНежилогоПомещения)
|
||||
{
|
||||
contract.Item1 = new HouseManagement.SupplyResourceContractTypeApartmentBuildingOwner()
|
||||
{
|
||||
Item = ConvertToDRSOContragent(договор.Контрагент)
|
||||
};
|
||||
|
||||
contract.ContractBase = [HcsHouseManagementNsi.ОснованиеЗаключенияДоговора.ЗаявлениеПотребителя];
|
||||
}
|
||||
|
||||
if (договор.ЭтоДоговорИКУ)
|
||||
{
|
||||
if (договор.Контрагент.ГуидОрганизации == null)
|
||||
throw new HcsException($"В договоре ИКУ {договор.НомерДоговора} не указан ГУИД организации");
|
||||
|
||||
contract.Item1 = new HouseManagement.SupplyResourceContractTypeOrganization()
|
||||
{
|
||||
orgRootEntityGUID = FormatGuid(договор.Контрагент.ГуидОрганизации)
|
||||
};
|
||||
|
||||
contract.ContractBase = [HcsHouseManagementNsi.ОснованиеЗаключенияДоговора.ДоговорУправления];
|
||||
}
|
||||
|
||||
Guid contractSubjectGuid = Guid.NewGuid();
|
||||
contract.ContractSubject = [
|
||||
new HouseManagement.SupplyResourceContractTypeContractSubject() {
|
||||
ServiceType = HcsHouseManagementNsi.ElectricSupplyServiceType,
|
||||
MunicipalResource = HcsHouseManagementNsi.ElectricSupplyMunicipalResource,
|
||||
StartSupplyDate = (договор.ДатаЗаключения != null ? (DateTime)договор.ДатаЗаключения : DateTime.Now),
|
||||
EndSupplyDate = DateTime.Now.AddYears(50),
|
||||
TransportGUID = FormatGuid(contractSubjectGuid)
|
||||
}
|
||||
];
|
||||
|
||||
// Порядок размещения информации о начислениях за коммунальные услуги ведется.
|
||||
// "D" - в разрезе договора. "O" - в разрезе объектов. Обязательно для ИКУ.
|
||||
if (договор.ЭтоДоговорИКУ)
|
||||
{
|
||||
contract.AccrualProcedure = HouseManagement.SupplyResourceContractTypeAccrualProcedure.D;
|
||||
contract.AccrualProcedureSpecified = true;
|
||||
}
|
||||
|
||||
if (договор.ЭтоДоговорИКУ)
|
||||
{
|
||||
// Размещение информации о начислениях за коммунальные услуги осуществляет.
|
||||
// R(SO)- РСО. P(roprietor)-Исполнитель коммунальных услуг. Обязательно для ИКУ.
|
||||
contract.CountingResource =
|
||||
договор.НачисленияРазмещаетРСО ?
|
||||
HouseManagement.SupplyResourceContractTypeCountingResource.R :
|
||||
HouseManagement.SupplyResourceContractTypeCountingResource.P;
|
||||
contract.CountingResourceSpecified = true;
|
||||
|
||||
if (договор.НачисленияРазмещаетРСО)
|
||||
{
|
||||
if (договор.ПриборыРазмещаетРСО)
|
||||
{
|
||||
contract.MeteringDeviceInformation = true;
|
||||
contract.MeteringDeviceInformationSpecified = true;
|
||||
}
|
||||
}
|
||||
|
||||
// В договоре нет планового объема потребления
|
||||
contract.IsPlannedVolume = false;
|
||||
}
|
||||
|
||||
if (договор.НачисленияРазмещаетРСО)
|
||||
{
|
||||
// Cрок предоставления платежных документов, не позднее
|
||||
contract.BillingDate = new HouseManagement.SupplyResourceContractTypeBillingDate()
|
||||
{
|
||||
Date = 15,
|
||||
DateType = HouseManagement.SupplyResourceContractTypeBillingDateDateType.N // Следующий месяц
|
||||
};
|
||||
|
||||
// Срок предоставления информации о поступивших платежах, не позднее
|
||||
contract.ProvidingInformationDate = new HouseManagement.SupplyResourceContractTypeProvidingInformationDate()
|
||||
{
|
||||
Date = 15,
|
||||
DateType = HouseManagement.SupplyResourceContractTypeProvidingInformationDateDateType.N // Следующий месяц
|
||||
};
|
||||
}
|
||||
|
||||
if (договор.ПриборыРазмещаетРСО)
|
||||
{
|
||||
// Период передачи текущих показаний должен быть указан, если ИПУ размещает РСО
|
||||
contract.Period = new HouseManagement.SupplyResourceContractTypePeriod()
|
||||
{
|
||||
Start = new HouseManagement.SupplyResourceContractTypePeriodStart()
|
||||
{
|
||||
StartDate = 1
|
||||
},
|
||||
End = new HouseManagement.SupplyResourceContractTypePeriodEnd()
|
||||
{
|
||||
EndDate = 25
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Срок представления (выставления) платежных документов, не позднее. Является обязательным,
|
||||
// если вторая сторона договора отличается от "Управляющая организация".
|
||||
if (договор.ЭтоДоговорНежилогоПомещения)
|
||||
{
|
||||
contract.BillingDate = new HouseManagement.SupplyResourceContractTypeBillingDate()
|
||||
{
|
||||
Date = -1, // последний день месяца
|
||||
DateType = HouseManagement.SupplyResourceContractTypeBillingDateDateType.N // следующего месяца
|
||||
};
|
||||
|
||||
// Объем поставки определяется на основании прибора учета (признак необходим чтобы
|
||||
// ГИС разрешал размещать ПУ на лицевых счетах договора) (признак запрещен для ИКУ)
|
||||
contract.VolumeDepends = true;
|
||||
contract.VolumeDependsSpecified = true;
|
||||
|
||||
// Период передачи текущих показаний должен быть указан если указано VolumeDepends
|
||||
contract.Period = new HouseManagement.SupplyResourceContractTypePeriod()
|
||||
{
|
||||
Start = new HouseManagement.SupplyResourceContractTypePeriodStart()
|
||||
{
|
||||
StartDate = 1
|
||||
},
|
||||
End = new HouseManagement.SupplyResourceContractTypePeriodEnd()
|
||||
{
|
||||
EndDate = 25
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Срок действия договора
|
||||
contract.ItemsElementName = [HouseManagement.ItemsChoiceType25.IndefiniteTerm];
|
||||
contract.Items = [true];
|
||||
|
||||
// Данные об объекте жилищного фонда. При импорте договора должен быть добавлен
|
||||
// как минимум один адрес объекта жилищного фонда.
|
||||
if (адреса != null)
|
||||
{
|
||||
contract.ObjectAddress = адреса.Select(
|
||||
адрес => ConvertToObjectAddress(договор, адрес, contractSubjectGuid)).ToArray();
|
||||
}
|
||||
|
||||
return contract;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Сборка сведений для отправки указателя на файл приложения к договору
|
||||
/// http://open-gkh.ru/Base/AttachmentType.html
|
||||
/// </summary>
|
||||
private HouseManagement.AttachmentType ConvertToAttachment(ГисПриложение приложение)
|
||||
{
|
||||
return new HouseManagement.AttachmentType()
|
||||
{
|
||||
Name = приложение.ИмяПриложения ?? throw new HcsException("Не указано имя файла приложения"),
|
||||
Description = приложение.ОписаниеПриложения != null ? приложение.ОписаниеПриложения : приложение.ИмяПриложения,
|
||||
AttachmentHASH = приложение.ХэшПриложения ?? throw new HcsException("Не указан хэш файла приложения"),
|
||||
Attachment = new HouseManagement.Attachment()
|
||||
{
|
||||
AttachmentGUID = FormatGuid(приложение.ГуидПриложения)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private HouseManagement.SupplyResourceContractTypeObjectAddress ConvertToObjectAddress(
|
||||
ГисДоговор договор, ГисАдресныйОбъект адрес, Guid contractSubjectGuid)
|
||||
{
|
||||
// Дату начала снабжения выводим из даты заключения договора
|
||||
DateTime startSupplyDate = (договор.ДатаЗаключения != null) ?
|
||||
(DateTime)договор.ДатаЗаключения : DateTime.Now;
|
||||
|
||||
// Ссылка на пару определения ресурсов предмета договора
|
||||
var pair = new HouseManagement.SupplyResourceContractTypeObjectAddressPair();
|
||||
pair.PairKey = FormatGuid(contractSubjectGuid);
|
||||
pair.StartSupplyDate = startSupplyDate;
|
||||
// TODO: Проверить комментарий
|
||||
pair.EndSupplyDateSpecified = false; // Не указана дата окончания поставки ресурса
|
||||
|
||||
var address = new HouseManagement.SupplyResourceContractTypeObjectAddress()
|
||||
{
|
||||
TransportGUID = FormatGuid(Guid.NewGuid()),
|
||||
FIASHouseGuid = FormatGuid(адрес.ГуидЗданияФиас),
|
||||
ApartmentNumber = MakeEmptyNull(адрес.НомерПомещения),
|
||||
RoomNumber = MakeEmptyNull(адрес.НомерКомнаты),
|
||||
Pair = [pair]
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(адрес.ТипЗдания))
|
||||
{
|
||||
address.HouseTypeSpecified = true;
|
||||
address.HouseType = ConvertToHouseType(адрес.ТипЗдания);
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
private HouseManagement.ObjectAddressTypeHouseType ConvertToHouseType(string типЗдания)
|
||||
{
|
||||
return типЗдания switch
|
||||
{
|
||||
ГисАдресныйОбъект.ИзвестныеТипыЗдания.MKD => HouseManagement.ObjectAddressTypeHouseType.MKD,
|
||||
ГисАдресныйОбъект.ИзвестныеТипыЗдания.ZHD => HouseManagement.ObjectAddressTypeHouseType.ZHD,
|
||||
ГисАдресныйОбъект.ИзвестныеТипыЗдания.ZHDBlockZastroyki => HouseManagement.ObjectAddressTypeHouseType.ZHDBlockZastroyki,
|
||||
_ => throw new HcsException($"Указан неизвестный тип здания [{типЗдания}]")
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Преобразует реквизиты контрагента в модель данных ГИС ЖКХ
|
||||
/// </summary>
|
||||
private object ConvertToDRSOContragent(ГисКонтрагент контрагент)
|
||||
{
|
||||
if (контрагент.ГуидОрганизации != null)
|
||||
{
|
||||
return new HouseManagement.DRSORegOrgType()
|
||||
{
|
||||
orgRootEntityGUID = FormatGuid(контрагент.ГуидОрганизации)
|
||||
};
|
||||
}
|
||||
|
||||
if (контрагент.Индивид != null)
|
||||
{
|
||||
контрагент.Индивид.ПроверитьЗаполнениеСНИЛС();
|
||||
контрагент.Индивид.ПроверитьЗаполнениеФИО();
|
||||
|
||||
return new HouseManagement.DRSOIndType()
|
||||
{
|
||||
Patronymic = MakeEmptyNull(контрагент.Индивид.Отчество),
|
||||
FirstName = MakeEmptyNull(контрагент.Индивид.Имя),
|
||||
Surname = MakeEmptyNull(контрагент.Индивид.Фамилия),
|
||||
Item = MakeEmptyNull(контрагент.Индивид.СНИЛСТолькоЦифры) // В СНИЛС требуется только 11 цифр
|
||||
};
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Выполнение операции размещения факта расторжения договора
|
||||
/// http://open-gkh.ru/HouseManagement/importSupplyResourceContractRequest/Contract/TerminateContract.html
|
||||
/// </summary>
|
||||
public async Task<DateTime> TerminateContract(
|
||||
ГисДоговор договор, DateTime датаРасторжения, CancellationToken token)
|
||||
{
|
||||
var terminate = new HouseManagement.importSupplyResourceContractRequestContractTerminateContract();
|
||||
terminate.Terminate = датаРасторжения;
|
||||
terminate.ReasonRef = HcsHouseManagementNsi.ПричинаРасторженияДоговора.ПоВзаимномуСогласиюСторон;
|
||||
return await CallImportContract(договор.ГуидДоговора, terminate, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Выполнение операции размещения факта аннулирование договора
|
||||
/// http://open-gkh.ru/HouseManagement/AnnulmentType.html
|
||||
/// </summary>
|
||||
public async Task<DateTime> AnnulContract(ГисДоговор договор, string причина, CancellationToken token)
|
||||
{
|
||||
var annulment = new HouseManagement.AnnulmentType();
|
||||
annulment.ReasonOfAnnulment = причина;
|
||||
return await CallImportContract(договор.ГуидДоговора, annulment, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,133 @@
|
||||
using Hcs.ClientApi.DataTypes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HouseManagement = Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Метод добавления/изменения/удаления элементов списка адресных объектов
|
||||
/// в договоре ресурсоснабжения
|
||||
/// </summary>
|
||||
public class HcsMethodImportSupplyResourceContractObjectAddress : HcsHouseManagementMethod
|
||||
{
|
||||
public HcsMethodImportSupplyResourceContractObjectAddress
|
||||
(HcsClientConfig config) : base(config)
|
||||
{
|
||||
EnableMinimalResponseWaitDelay = true;
|
||||
CanBeRestarted = true;
|
||||
}
|
||||
|
||||
public async Task ImportObjectAddresses(
|
||||
ГисДоговор договор,
|
||||
IEnumerable<ГисАдресныйОбъект> адресаДляРазмещения,
|
||||
IEnumerable<ГисАдресныйОбъект> адресаДляУдаления,
|
||||
CancellationToken token)
|
||||
{
|
||||
if (договор == null) throw new ArgumentNullException(nameof(договор));
|
||||
|
||||
var list = new List<HouseManagement.importSupplyResourceContractObjectAddressRequestObjectAddress>();
|
||||
if (адресаДляРазмещения != null) list.AddRange(адресаДляРазмещения.Select(AdoptForLoading));
|
||||
if (адресаДляУдаления != null) list.AddRange(адресаДляУдаления.Select(AdoptForRemoval));
|
||||
|
||||
var request = new HouseManagement.importSupplyResourceContractObjectAddressRequest()
|
||||
{
|
||||
Id = HcsConstants.SignedXmlElementId,
|
||||
Item = FormatGuid(договор.ГуидДоговора),
|
||||
ItemElementName = HouseManagement.ItemChoiceType28.ContractRootGUID,
|
||||
ObjectAddress = list.ToArray()
|
||||
// TODO: Проверить комментарий
|
||||
//version = "13.1.1.1" // Версия указана в API
|
||||
};
|
||||
|
||||
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
|
||||
{
|
||||
var ackResponse = await portClient.importSupplyResourceContractObjectAddressDataAsync(
|
||||
CreateRequestHeader(), request);
|
||||
return ackResponse.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
ParseImportResults(stateResult, list.Count(), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Готовит структуру адресного объекта для удаления в ГИС
|
||||
/// </summary>
|
||||
private HouseManagement.importSupplyResourceContractObjectAddressRequestObjectAddress AdoptForRemoval(
|
||||
ГисАдресныйОбъект адрес)
|
||||
{
|
||||
if (адрес == null) throw new ArgumentNullException(nameof(адрес));
|
||||
|
||||
Guid transportGuid = Guid.NewGuid();
|
||||
|
||||
bool deleteObject = true;
|
||||
|
||||
return new HouseManagement.importSupplyResourceContractObjectAddressRequestObjectAddress()
|
||||
{
|
||||
TransportGUID = FormatGuid(transportGuid),
|
||||
ObjectGUID = FormatGuid(адрес.ГуидАдресногоОбъекта),
|
||||
Item = deleteObject
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Готовит структуру адресного объекта для добавления/обновления в ГИС
|
||||
/// </summary>
|
||||
private HouseManagement.importSupplyResourceContractObjectAddressRequestObjectAddress AdoptForLoading(
|
||||
ГисАдресныйОбъект адрес)
|
||||
{
|
||||
if (адрес == null) throw new ArgumentNullException(nameof(адрес));
|
||||
|
||||
Guid transportGuid = Guid.NewGuid();
|
||||
|
||||
var serviceType = new HouseManagement.ContractSubjectObjectAdressTypeServiceType()
|
||||
{
|
||||
Code = HcsHouseManagementNsi.ElectricSupplyServiceType.Code,
|
||||
GUID = HcsHouseManagementNsi.ElectricSupplyServiceType.GUID,
|
||||
Name = HcsHouseManagementNsi.ElectricSupplyServiceType.Name
|
||||
};
|
||||
|
||||
var municipalResource = new HouseManagement.ContractSubjectObjectAdressTypeMunicipalResource()
|
||||
{
|
||||
Code = HcsHouseManagementNsi.ElectricSupplyMunicipalResource.Code,
|
||||
GUID = HcsHouseManagementNsi.ElectricSupplyMunicipalResource.GUID,
|
||||
Name = HcsHouseManagementNsi.ElectricSupplyMunicipalResource.Name
|
||||
};
|
||||
|
||||
var pair = new HouseManagement.importSupplyResourceContractObjectAddressRequestObjectAddressLoadObjectPair()
|
||||
{
|
||||
// TODO: Проверить комментарий
|
||||
TransportGUID = FormatGuid(Guid.NewGuid()), // Получал BadRequest пока не сделал здесь новый GUID
|
||||
ServiceType = serviceType,
|
||||
MunicipalResource = municipalResource,
|
||||
// TODO: Проверить комментарий
|
||||
StartSupplyDate = DateTime.Now // В договоре нет даты начала снабжения адреса, ставлю что-нибудь
|
||||
};
|
||||
|
||||
var loadObject = new HouseManagement.importSupplyResourceContractObjectAddressRequestObjectAddressLoadObject()
|
||||
{
|
||||
FIASHouseGuid = FormatGuid(адрес.ГуидЗданияФиас),
|
||||
ApartmentNumber = MakeEmptyNull(адрес.НомерПомещения),
|
||||
RoomNumber = MakeEmptyNull(адрес.НомерКомнаты),
|
||||
Pair = [pair]
|
||||
};
|
||||
|
||||
var address = new HouseManagement.importSupplyResourceContractObjectAddressRequestObjectAddress()
|
||||
{
|
||||
TransportGUID = FormatGuid(transportGuid),
|
||||
Item = loadObject
|
||||
};
|
||||
|
||||
if (адрес.ГуидАдресногоОбъекта != default)
|
||||
{
|
||||
address.ObjectGUID = FormatGuid(адрес.ГуидАдресногоОбъекта);
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
using Hcs.ClientApi.DataTypes;
|
||||
using Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HouseManagement = Hcs.Service.Async.HouseManagement.v14_5_0_1;
|
||||
|
||||
namespace Hcs.ClientApi.HouseManagementApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Метод отправки в ГИС проекта договора ресурсоснабжения, удаления
|
||||
/// проекта договора РСО, перевода проекта в статус Размещенные
|
||||
/// </summary>
|
||||
public class HcsMethodImportSupplyResourceContractProject : HcsHouseManagementMethod
|
||||
{
|
||||
public HcsMethodImportSupplyResourceContractProject
|
||||
(HcsClientConfig config) : base(config)
|
||||
{
|
||||
EnableMinimalResponseWaitDelay = true;
|
||||
CanBeRestarted = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Выполнение удаления в ГИС проекта договора
|
||||
/// </summary>
|
||||
public async Task DeleteContractProject(ГисДоговор договор, CancellationToken token)
|
||||
{
|
||||
await DoContractProjectOperation(
|
||||
договор, Item1ChoiceType10.DeleteContractProject, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Выполнение перевода проекта договора в статус Размещен
|
||||
/// </summary>
|
||||
public async Task PlaceContractProject(ГисДоговор договор, CancellationToken token)
|
||||
{
|
||||
await DoContractProjectOperation(
|
||||
договор, Item1ChoiceType10.PlacingContractProject, token);
|
||||
}
|
||||
|
||||
private async Task DoContractProjectOperation(
|
||||
ГисДоговор договор, Item1ChoiceType10 operationType, CancellationToken token)
|
||||
{
|
||||
if (договор == null) throw new ArgumentNullException(nameof(договор));
|
||||
if (договор.ГуидВерсииДоговора == default)
|
||||
throw new ArgumentException("Для проекта договора не указан ГУИД версии");
|
||||
|
||||
var contract = new HouseManagement.importSupplyResourceContractProjectRequestContract()
|
||||
{
|
||||
TransportGUID = FormatGuid(Guid.NewGuid()),
|
||||
ItemElementName = ItemChoiceType29.ContractRootGUID,
|
||||
Item = FormatGuid(договор.ГуидДоговора),
|
||||
// TODO: Проверить комментарий
|
||||
// Если удалять версию проекта то остается предыдущая версия проекта
|
||||
//ItemElementName = ItemChoiceType29.ContractGUID,
|
||||
//Item = FormatGuid(договор.ГуидВерсииДоговора),
|
||||
Item1ElementName = operationType,
|
||||
Item1 = true,
|
||||
};
|
||||
|
||||
var request = new HouseManagement.importSupplyResourceContractProjectRequest()
|
||||
{
|
||||
Id = HcsConstants.SignedXmlElementId,
|
||||
Contract = [contract],
|
||||
// TODO: Проверить комментарий
|
||||
//version = "13.1.1.1" // Версия указана в API
|
||||
};
|
||||
|
||||
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
|
||||
{
|
||||
var ackResponse = await portClient.importSupplyResourceContractProjectDataAsync(
|
||||
CreateRequestHeader(), request);
|
||||
return ackResponse.AckRequest.Ack;
|
||||
}, token);
|
||||
|
||||
ParseSingleImportResult(stateResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user