Add project
Basic formatting applied. Unnecessary comments have been removed. Suspicious code is covered by TODO.
This commit is contained in:
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user