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
{
///
/// Метод получения реестра договоров ресурсоснабжения (ДРСО)
///
public class HcsMethodExportSupplyResourceContractData : HcsHouseManagementMethod
{
public HcsMethodExportSupplyResourceContractData(HcsClientConfig config) : base(config)
{
CanBeRestarted = true;
}
///
/// Получает один договор ресурсоснабжения по его GUID
///
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 договор;
}
///
/// Получает один договор ресурсоснабжения по его номеру договора
///
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();
}
///
/// Получает полный список реестра договоров ресурсоснабжения
///
public async Task 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 QueryOneBatch(
Guid? contractRootGuid, string contractNumber, Action<ГисДоговор> resultHandler,
Guid? exportNextGuid, CancellationToken token)
{
var itemNames = new List { };
List items = new List { };
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
(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
};
}
///
/// Разбор сведений о контрагенте - второй стороне договора
///
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 ГисКонтрагент() { ТипКонтрагента = ГисТипКонтрагента.НеУказано };
}
///
/// Разбор ссылки на контрагента - второй стороны договора
///
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);
}
}
}
}