Files
hcs/Hcs.Client/ClientApi/HouseManagementApi/HcsMethodImportSupplyResourceContractData.cs
HOME-LAPTOP\kshkulev 33ab055b43 Add project
Basic formatting applied. Unnecessary comments have been removed. Suspicious code is covered by TODO.
2025-08-12 11:21:10 +09:00

387 lines
22 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}
}