Remove old code and services

This commit is contained in:
2025-09-08 19:13:42 +09:00
parent 8b3e1249c0
commit b97faed2af
241 changed files with 0 additions and 135489 deletions

View File

@ -1,35 +0,0 @@
using System;
namespace Hcs.ClientApi.DataTypes
{
/// <summary>
/// Информация о зданиях и помещениях в зданиях (объектах жилого фонда),
/// которые связаны с договором (в договоре имеются Лицевые Счета в
/// указанных объектах)
/// </summary>
public class ГисАдресныйОбъект
{
public Guid ГуидДоговора;
public Guid ГуидВерсииДоговора;
public Guid ГуидЗданияФиас;
public Guid ГуидАдресногоОбъекта;
public class ИзвестныеТипыЗдания
{
public const string MKD = "MKD";
public const string ZHD = "ZHD";
public const string ZHDBlockZastroyki = "ZHDBlockZastroyki";
}
public string ТипЗдания;
public string НомерПомещения;
public string НомерКомнаты;
public bool СвязанСДоговором(ГисДоговор договор) => договор != null && договор.ГуидДоговора == ГуидДоговора;
public override string ToString()
{
return $"Тип=[{ТипЗдания}] ЗданиеФиас=[{ГуидЗданияФиас}] Объект[{ГуидАдресногоОбъекта}] Помещ[{НомерПомещения}] Комн[{НомерКомнаты}]";
}
}
}

View File

@ -1,140 +0,0 @@
using Newtonsoft.Json;
using System;
namespace Hcs.ClientApi.DataTypes
{
/// <summary>
/// Договор с ресурсоснабжающей организацией
/// </summary>
public class ГисДоговор
{
public Guid ГуидДоговора;
public Guid ГуидВерсииДоговора;
public string НомерВерсии;
public ГисСостояниеДоговора СостояниеДоговора;
public ГисСтатусВерсииДоговора СтатусВерсииДоговора;
public ГисТипДоговораРСО ТипДоговораРСО;
public string НомерДоговора;
public DateTime? ДатаЗаключения;
public DateTime? ДатаВступленияВСилу;
public bool НачисленияРазмещаетРСО;
public bool ПриборыРазмещаетРСО;
public ГисКонтрагент Контрагент;
public ГисПредметДоговора[] ПредметыДоговора;
public ГисПриложение[] ПриложенияДоговора;
[JsonIgnore]
public bool ЭтоДоговорИКУ => (ТипДоговораРСО == ГисТипДоговораРСО.НеПубличныйИлиНеНежилые);
[JsonIgnore]
public bool ЭтоДоговорНежилогоПомещения => (ТипДоговораРСО == ГисТипДоговораРСО.ПубличныйИлиНежилые);
[JsonIgnore]
public bool ЭтоПроектДоговора => (СтатусВерсииДоговора == ГисСтатусВерсииДоговора.Проект);
[JsonIgnore]
public bool Расторгнут => (СтатусВерсииДоговора == ГисСтатусВерсииДоговора.Расторгнут);
[JsonIgnore]
public bool ИмеетГуидДоговора => (ГуидДоговора != default);
[JsonIgnore]
public bool ПриниматьИзГисНаАнализ
{
get
{
return СтатусВерсииДоговора switch
{
// TODO: Проверить комментирование этой строчки
//ГисСтатусВерсииДоговора.Проект => false, // С 15.11.2024 принимаем проекты
ГисСтатусВерсииДоговора.Аннулирован => false,
ГисСтатусВерсииДоговора.Расторгнут => false,
_ => true
};
}
}
public override string ToString()
{
return $"Договор №{НомерДоговора} Тип={ТипДоговораРСО}" +
$" Статус={СтатусВерсииДоговора} Состояние={СостояниеДоговора}" +
$" Заключен={HcsUtil.FormatDate(ДатаЗаключения)}" +
$" №Версии={НомерВерсии} ГуидДог={ГуидДоговора}" +
$" ГуидВерсии={ГуидВерсииДоговора}";
}
}
public enum ГисТипДоговораРСО
{
/// <summary>
/// Договор не является публичным и/или присутствует заключенный на бумажном
/// носителе (электронной форме) и/или не заключен в отношении нежилых помещений
/// в многоквартирных домах (IsContract в терминах HCS)
/// </summary>
НеПубличныйИлиНеНежилые,
/// <summary>
/// Договор является публичным и/или отсутствует заключенный на бумажном носителе
/// (в электронной форме) и/или заключен в отношении нежилых помещений в
/// многоквартирных домах (IsNotContract в терминах HCS)
/// </summary>
ПубличныйИлиНежилые
}
public enum ГисСостояниеДоговора
{
НеВступилВСилу, // NotTakeEffect
Действующий, // Proceed
ИстекСрокДействия // Expired
}
public enum ГисСтатусВерсииДоговора
{
Размещен, // Posted
Расторгнут, // Terminated
Проект, // Draft
Аннулирован // Annul
}
public class ГисПредметДоговора
{
// Вид КУ. Ссылка на НСИ "Вид коммунальной услуги" (реестровый номер 3)
public string КодНсиУслуги;
public Guid ГуидНсиУслуги;
public string ИмяНсиУслуги;
// Коммунальный ресурс. Ссылка на НСИ "Тарифицируемый ресурс" (реестровый номер 239)
public string КодНсиРесурса;
public Guid ГуидНсиРесурса;
public string ИмяНсиРесурса;
}
public class ГисПриложение
{
/// <summary>
/// Имя файла приложения
/// </summary>
public string ИмяПриложения;
/// <summary>
/// Пояснение к файлу приложения
/// </summary>
public string ОписаниеПриложения;
/// <summary>
/// ГУИД файла приложения из ext-bus-file-store-service
/// </summary>
public Guid ГуидПриложения;
/// <summary>
/// Хэш файла приложения в устаревшем стандарте "ГОСТ Р 34.11-94" в Binhex
/// </summary>
public string ХэшПриложения;
}
}

View File

@ -1,197 +0,0 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Hcs.ClientApi.DataTypes
{
/// <summary>
/// Сборный класс для получения сразу всех договоров, их лицевых счетов
/// и приборов учета привязанных к лицевым счетам договоров
/// </summary>
public class ГисДоговорыИПриборы
{
public DateTime ДатаНачалаСборки;
public DateTime ДатаКонцаСборки;
/// <summary>
/// Договоры ресурсоснабжения
/// </summary>
public List<ГисДоговор> ДоговорыРСО = new List<ГисДоговор>();
public List<ГисАдресныйОбъект> АдресаОбъектов = new List<ГисАдресныйОбъект>();
public List<ГисЗдание> Здания = new List<ГисЗдание>();
public List<ГисЛицевойСчет> ЛицевыеСчета = new List<ГисЛицевойСчет>();
public List<ГисПриборУчета> ПриборыУчета = new List<ГисПриборУчета>();
public ГисДоговор НайтиДоговорПоНомеру(string номерДоговора)
=> ДоговорыРСО.FirstOrDefault(x => x.НомерДоговора == номерДоговора);
public bool ЭтотЛицевойСчетСвязанСДоговорами(ГисЛицевойСчет лс)
{
return ДоговорыРСО.Any(договор => лс.СвязанСДоговором(договор));
}
public ГисЗдание НайтиЗданиеПомещения(Guid гуидПомещения)
{
foreach (var здание in Здания)
{
foreach (var помещение in здание.Помещения)
{
if (помещение.ГуидПомещения == гуидПомещения) return здание;
}
}
return null;
}
public ГисЗдание НайтиЗданиеЛицевогоСчета(ГисЛицевойСчет лс)
{
if (лс.Размещения == null) return null;
foreach (var размещение in лс.Размещения)
{
if (размещение.ГуидПомещения == null) continue;
var здание = НайтиЗданиеПомещения((Guid)размещение.ГуидПомещения);
if (здание != null) return здание;
}
return null;
}
public void УдалитьЛицевыеСчетаЗдания(Guid гуидЗданияФиас)
{
var здание = Здания.FirstOrDefault(x => x.ГуидЗданияФиас == гуидЗданияФиас);
if (здание == null || здание.Помещения == null) return;
var лсДляУдаления = new List<ГисЛицевойСчет>();
var гуидыПомещенийЗдания = new HashSet<Guid>(здание.Помещения.Select(x => x.ГуидПомещения));
foreach (var лс in ЛицевыеСчета)
{
if (лс.Размещения == null) continue;
foreach (var размещениеЛС in лс.Размещения)
{
if (размещениеЛС.ГуидПомещения == null) continue;
if (гуидыПомещенийЗдания.Contains((Guid)размещениеЛС.ГуидПомещения))
{
лсДляУдаления.Add(лс);
break;
}
}
}
foreach (var лсУдалить in лсДляУдаления)
ЛицевыеСчета.Remove(лсУдалить);
}
public int ЗаменитьЛицевыеСчетаЗданияВЛокальномСнимке(
Guid гуидЗданияФиас, IEnumerable<ГисЛицевойСчет> лицевые)
{
УдалитьЛицевыеСчетаЗдания(гуидЗданияФиас);
var живые = лицевые.Where(лс => лс.ДействуетСейчас && ЭтотЛицевойСчетСвязанСДоговорами(лс));
ЛицевыеСчета.AddRange(живые);
return живые.Count();
}
public bool ЭтотПриборСвязанСЛицевымиСчетами(ГисПриборУчета прибор)
{
return ЛицевыеСчета.Any(лс => прибор.СвязанСЛицевымСчетом(лс));
}
public IEnumerable<ГисАдресныйОбъект> ДатьАдресаОбъектовДоговора(ГисДоговор договор)
{
return АдресаОбъектов.Where(x => x.СвязанСДоговором(договор));
}
public IEnumerable<ГисПриборУчета> ДатьПриборыУчетаДоговора(ГисДоговор договор)
{
var адресаДоговора = ДатьАдресаОбъектовДоговора(договор).ToArray();
var лицевыеДоговора = ЛицевыеСчета.Where(x => x.СвязанСДоговором(договор)).ToArray();
var приборы = new List<ГисПриборУчета>();
foreach (var прибор in ПриборыУчета)
{
if (прибор == null) continue;
if (договор.ЭтоДоговорИКУ)
{
foreach (var адрес in адресаДоговора)
{
if (прибор.СвязанСАдреснымОбъектом(адрес)) приборы.Add(прибор);
}
}
if (договор.ЭтоДоговорНежилогоПомещения)
{
foreach (var лицевой in лицевыеДоговора)
{
if (прибор.СвязанСЛицевымСчетом(лицевой)) приборы.Add(прибор);
}
}
}
return приборы;
}
public IEnumerable<ГисПомещение> ДатьПомещенияАдресногоОбъекта(ГисАдресныйОбъект адрес)
{
var здание = Здания.FirstOrDefault(x => x.ГуидЗданияФиас == адрес.ГуидЗданияФиас);
if (здание == null) return new List<ГисПомещение>();
return здание.Помещения;
}
public IEnumerable<ГисПриборУчета> ДатьПриборыУчетаЛицевогоСчета(ГисЛицевойСчет лс)
{
return ПриборыУчета.Where(x => x.СвязанСЛицевымСчетом(лс));
}
public ГисЗданиеПомещение НайтиПомещениеЛицевогоСчета(ГисЛицевойСчет лс)
{
foreach (var размещение in лс.Размещения)
{
foreach (var здание in Здания)
{
if (здание.Помещения == null) continue;
foreach (var помещение in здание.Помещения)
{
if (помещение.ГуидПомещения == размещение.ГуидПомещения)
{
return new ГисЗданиеПомещение(здание, помещение);
}
}
}
}
return new ГисЗданиеПомещение(null, null);
}
public static ГисДоговорыИПриборы ПрочитатьФайлJson(string jsonFileName)
{
using (StreamReader file = File.OpenText(jsonFileName))
{
JsonSerializer serializer = new JsonSerializer();
return (ГисДоговорыИПриборы)serializer.Deserialize(file, typeof(ГисДоговорыИПриборы));
}
}
public void ЗаписатьФайлJson(string jsonFileName)
{
using (StreamWriter file = File.CreateText(jsonFileName))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(file, this);
}
}
public override string ToString()
{
return $"ДоговорыРСО={ДоговорыРСО.Count} Адреса={АдресаОбъектов.Count}" +
$" ЛС={ЛицевыеСчета.Count} ПУ={ПриборыУчета.Count}";
}
}
}

View File

@ -1,24 +0,0 @@
using System;
using System.Linq;
namespace Hcs.ClientApi.DataTypes
{
/// <summary>
/// Дом ГИС ЖКХ
/// </summary>
public class ГисЗдание
{
public ГисТипДома ТипДома;
public Guid ГуидЗданияФиас;
public string НомерДомаГис;
public ГисПомещение[] Помещения;
public override string ToString()
{
return $"{ТипДома} дом №ГИС={НомерДомаГис} Помещения={Помещения.Count()}";
}
}
public enum ГисТипДома { Многоквартирный, Жилой };
}

View File

@ -1,8 +0,0 @@
namespace Hcs.ClientApi.DataTypes
{
public record struct ГисЗданиеПомещение(ГисЗдание Здание, ГисПомещение Помещение)
{
public bool Пустое => (Здание == null || Помещение == null);
public bool Заполнено => !Пустое;
}
}

View File

@ -1,72 +0,0 @@
using Newtonsoft.Json;
using System;
using System.Linq;
namespace Hcs.ClientApi.DataTypes
{
/// <summary>
/// Сведения о контрагенте договора РСО
/// </summary>
public class ГисКонтрагент
{
public ГисТипКонтрагента ТипКонтрагента;
/// <summary>
/// ГУИД из реестра организаций ГИС ЖКХ
/// </summary>
public Guid? ГуидОрганизации;
/// <summary>
/// ГУИД версии организации из реестра организаций ГИС ЖКХ необходим
/// для размещения Лицевого счета
/// </summary>
public Guid? ГуидВерсииОрганизации;
/// <summary>
/// Сведения об индивидуальном физическом лице
/// </summary>
public ГисИндивид Индивид;
}
public enum ГисТипКонтрагента
{
НеУказано,
ВладелецПомещения,
УправляющаяКомпания
}
public class ГисИндивид
{
public string Фамилия;
public string Имя;
public string Отчество;
public string СНИЛС;
public string НомерДокумента;
public string СерияДокумента;
public DateTime? ДатаДокумента;
[JsonIgnore]
public bool СНИЛСЗаполнен
=> !string.IsNullOrEmpty(СНИЛС);
[JsonIgnore]
public string СНИЛСТолькоЦифры
=> СНИЛСЗаполнен ? string.Concat(СНИЛС.Where(char.IsDigit)) : null;
[JsonIgnore]
public bool СНИЛСЗаполненВернойДлины
=> (СНИЛСЗаполнен && СНИЛСТолькоЦифры.Length == 11);
public void ПроверитьЗаполнениеСНИЛС()
{
if (!СНИЛСЗаполненВернойДлины)
throw new HcsException($"В СНИЛС контрагента ФЛ должно быть указано 11 цифр: {СНИЛС}");
}
public void ПроверитьЗаполнениеФИО()
{
if (string.IsNullOrEmpty(Фамилия)) throw new HcsException("Не заполнена Фамилия контрагента ФЛ");
if (string.IsNullOrEmpty(Имя)) throw new HcsException("Не заполнено Имя контрагента ФЛ");
}
}
}

View File

@ -1,112 +0,0 @@
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Text;
namespace Hcs.ClientApi.DataTypes
{
/// <summary>
/// Лицевой счет из ГИС ЖКХ имеет номер единого лицевого счета (ЕЛС)
/// и выдается на каждую точку поставки в жилом доме для договора
/// по нежилым помещениям
/// </summary>
public class ГисЛицевойСчет
{
public Guid ГуидЛицевогоСчета;
public string НомерЛицевогоСчета;
public string НомерЕЛС;
public DateTime? ДатаСоздания;
public DateTime? ДатаЗакрытия;
public string КодНсиПричиныЗакрытия;
public string ИмяПричиныЗакрытия;
public decimal? ПолнаяПлощадь;
public decimal? ЖилаяПлощадь;
public string КодЖКУ;
public ГисРазмещениеЛС[] Размещения;
public ГисОснованиеЛС[] Основания;
public bool СвязанСДоговором(ГисДоговор договор)
{
if (договор != null && Основания != null && Основания.Any(
основание => основание.ГуидДоговора == договор.ГуидВерсииДоговора ||
основание.ГуидДоговора == договор.ГуидДоговора ||
string.Compare(основание.НомерДоговора, договор.НомерДоговора) == 0)) return true;
return false;
}
[JsonIgnore]
public bool ДействуетСейчас => (ДатаЗакрытия == null);
[JsonIgnore]
public string ОписаниеРазмещений
{
get
{
var accomod = new StringBuilder();
foreach (var x in Размещения) accomod.Append($"[{x}]");
return accomod.ToString();
}
}
[JsonIgnore]
public string ОписаниеОснований
{
get
{
if (Основания == null) return null;
var reasons = new StringBuilder();
foreach (var x in Основания) reasons.Append($"[{x}]");
return reasons.ToString();
}
}
public override string ToString()
{
return $"ЛС №{НомерЛицевогоСчета} ЕЛС={НомерЕЛС}" +
$" Создан={HcsUtil.FormatDate(ДатаСоздания)}" +
$" Закрыт={HcsUtil.FormatDate(ДатаЗакрытия)}" +
$" Размещения={ОписаниеРазмещений}" +
$" Основания={ОписаниеОснований}";
}
}
/// <summary>
/// Лицевой счет может быть привязан к нескольким размещениям.
/// Каждое размещение может быть или в здании, или в жилой комнате или в помещении
/// </summary>
public class ГисРазмещениеЛС
{
public Guid? ГуидЗдания;
public Guid? ГуидПомещения;
public Guid? ГуидЖилойКомнаты;
public decimal? ПроцентДоли;
public override string ToString()
{
if (ГуидЗдания != null) return $"Здание={ГуидЗдания}";
if (ГуидПомещения != null) return $"Помещение={ГуидПомещения}";
if (ГуидЖилойКомнаты != null) return $"ЖилКомната={ГуидЖилойКомнаты}";
return "";
}
}
public enum ГисТипОснованияЛС { ДоговорРСО, Соцнайм, Договор }
/// <summary>
/// Основание создания лицевого счета (договор на основании которого открыт ЛС)
/// </summary>
public class ГисОснованиеЛС
{
public ГисТипОснованияЛС ТипОснованияЛС;
public Guid ГуидДоговора;
public string НомерДоговора;
public override string ToString()
{
return $"{ТипОснованияЛС}={ГуидДоговора}";
}
}
}

View File

@ -1,57 +0,0 @@
using Newtonsoft.Json;
using System;
namespace Hcs.ClientApi.DataTypes
{
/// <summary>
/// Сведения из реестра оргнаизации ГИС ЖКХ
/// </summary>
public class ГисОрганизация
{
public Guid ГуидОрганизации;
public Guid ГуидВерсииОрганизации;
public ГисТипОрганизации ТипОрганизации;
public string КраткоеИмяОрганизации;
public string ПолноеИмяОрганизации;
public bool Действующая;
public string ИНН;
public string КПП;
public string ОГРН;
public string ОКОПФ;
public string Фамилия;
public string Имя;
public string Отчество;
public string ЮридическийАдрес;
public DateTime? ДатаЛиквидации;
[JsonIgnore]
public const int ДлинаОГРН = 13;
[JsonIgnore]
public const int ДлинаОГРНИП = 15;
public override string ToString()
{
string имя = ТипОрганизации == ГисТипОрганизации.ИП ?
$"ИП {Фамилия} {Имя} {Отчество}" : КраткоеИмяОрганизации;
return $"{ТипОрганизации}: [{имя}] ИНН={ИНН} КПП={КПП} Действующая={Действующая}" +
$" ГУИД={ГуидОрганизации} Версия={ГуидВерсииОрганизации}";
}
}
public enum ГисТипОрганизации { НетУказано, ЮЛ, ИП, Филиал, Иностранный }
}

View File

@ -1,43 +0,0 @@
using System;
using System.Text;
namespace Hcs.ClientApi.DataTypes
{
public class ГисПоказания
{
public DateTime ДатаСнятия;
public string ПоказанияТ1;
public string ПоказанияТ2;
public string ПоказанияТ3;
public override string ToString()
{
var buf = new StringBuilder();
if (!string.IsNullOrEmpty(ПоказанияТ1))
{
buf.AppendFormat("Т1={0}", ПоказанияТ1);
}
if (!string.IsNullOrEmpty(ПоказанияТ2))
{
if (buf.Length > 0) buf.Append(" ");
buf.AppendFormat("Т2={0}", ПоказанияТ2);
}
if (!string.IsNullOrEmpty(ПоказанияТ3))
{
if (buf.Length > 0) buf.Append(" ");
buf.AppendFormat("Т3={0}", ПоказанияТ3);
}
if (ДатаСнятия != default)
{
if (buf.Length > 0) buf.Append(" ");
buf.AppendFormat("на {0:d}", ДатаСнятия);
}
return buf.ToString();
}
}
}

View File

@ -1,8 +0,0 @@
namespace Hcs.ClientApi.DataTypes
{
public class ГисПолеЭлементаСправочника
{
public string наименование;
public string значение;
}
}

View File

@ -1,21 +0,0 @@
using System;
namespace Hcs.ClientApi.DataTypes
{
/// <summary>
/// Жилое или нежилое момещение в доме ГИС ЖКХ
/// </summary>
public class ГисПомещение
{
public Guid ГуидПомещения;
public bool ЭтоЖилоеПомещение;
public string НомерПомещения;
public DateTime? ДатаПрекращения;
public string Аннулирование;
public override string ToString()
{
return $"ГисПомещение={НомерПомещения} Жилое={ЭтоЖилоеПомещение} Guid={ГуидПомещения} Прекращено={ДатаПрекращения} Аннул={Аннулирование}";
}
}
}

View File

@ -1,102 +0,0 @@
using Newtonsoft.Json;
using System;
using System.Linq;
namespace Hcs.ClientApi.DataTypes
{
/// <summary>
/// Прибор учета из ГИС ЖКХ может быть привязан к списку зданий (ОДПУ)
/// или к списку Лицевых счетов (все виды кроме ОДПУ)
/// </summary>
public class ГисПриборУчета
{
public Guid ГуидПрибораУчета;
public Guid ГуидВерсииПрибора;
public string НомерПрибораУчетаГис;
public DateTime? ДатаРазмещенияВерсии;
public Guid ГуидВладельцаПрибора;
public ГисСтатусПрибораУчета СтатусПрибораУчета;
public ГисВидПрибораУчета ВидПрибораУчета;
public string ЗаводскойНомер;
public string МодельПрибораУчета;
[JsonIgnore]
public bool КоэффициентТрансформацииУказан => (КоэффициентТрансформации > 0);
public decimal КоэффициентТрансформации;
public string ПоказаниеТ1;
public string ПоказаниеТ2;
public string ПоказаниеТ3;
// TODO: Добавить эти комментарии как XML-комментарии
public DateTime? ДатаИзготовления; // Обязательно при импорте
public DateTime? ДатаУстановки;
public DateTime? ДатаВводаВЭксплуатацию; // Обязательно кроме ОДПУ
public DateTime? ДатаПоследнейПоверки; // Обязательно для ОДПУ
public bool РежимДистанционногоОпроса; // Признак наличия ИСУ
public string ОписаниеДистанционногоОпроса; // Наименование ИСУ
public Guid[] ГуидыЗданийФиас;
public Guid[] ГуидыЛицевыхСчетов;
public Guid[] ГуидыПомещений;
public Guid[] ГуидыЖилыхКомнат;
[JsonIgnore]
public bool ЭтоАктивный => (СтатусПрибораУчета == ГисСтатусПрибораУчета.Активный);
[JsonIgnore]
public bool ЭтоАрхивный => (СтатусПрибораУчета == ГисСтатусПрибораУчета.Архивный);
[JsonIgnore]
public bool ЭтоОДПУ => (ВидПрибораУчета == ГисВидПрибораУчета.ОДПУ);
[JsonIgnore]
public bool ЭтоНежилоеПомещение => (ВидПрибораУчета == ГисВидПрибораУчета.НежилоеПомещение);
[JsonIgnore]
public bool ЭтоПриборЮЛ => ЭтоОДПУ || ЭтоНежилоеПомещение;
public bool СвязанСЛицевымСчетом(ГисЛицевойСчет лс)
{
if (лс == null || ГуидыЛицевыхСчетов == null || ГуидыЛицевыхСчетов.Length == 0) return false;
if (ГуидыЛицевыхСчетов.Length == 1) return (ГуидыЛицевыхСчетов[0] == лс.ГуидЛицевогоСчета);
return ГуидыЛицевыхСчетов.Contains(лс.ГуидЛицевогоСчета);
}
public bool СвязанСАдреснымОбъектом(ГисАдресныйОбъект адрес)
{
// TODO: Для лицевых счетов здесь надо тестировать ГУИД помещения
if (адрес == null || ГуидыЗданийФиас == null || ГуидыЗданийФиас.Length == 0) return false;
if (ГуидыЗданийФиас.Length == 1) return ГуидыЗданийФиас[0] == адрес.ГуидЗданияФиас;
return ГуидыЗданийФиас.Contains(адрес.ГуидЗданияФиас);
}
public bool ЗаполненГуидЗданияФиас => (ГуидыЗданийФиас != null && ГуидыЗданийФиас.Length > 0);
public Guid? ОдинГуидЗданияФиас => (ЗаполненГуидЗданияФиас ? ГуидыЗданийФиас[0] : null);
public override string ToString()
{
int числоЛС = ГуидыЛицевыхСчетов != null ? ГуидыЛицевыхСчетов.Length : 0;
int числоДомов = ГуидыЗданийФиас != null ? ГуидыЗданийФиас.Length : 0;
return $"{ВидПрибораУчета} {СтатусПрибораУчета} №{ЗаводскойНомер} [{МодельПрибораУчета}]" +
$"Гуид={ГуидПрибораУчета} ЧислоЛС={числоЛС} ЧислоДомов={числоДомов}";
}
}
public enum ГисВидПрибораУчета
{
ЖилоеПомещение,
НежилоеПомещение,
ОДПУ,
ЖилойДом,
ЖилаяКомната,
КоммунальнаяКвартира
}
public enum ГисСтатусПрибораУчета { Активный, Архивный }
}

View File

@ -1,11 +0,0 @@
using System;
namespace Hcs.ClientApi.DataTypes
{
public class ГисСправочник
{
public string реестровыйНомер;
public DateTime датаФормирования;
public ГисЭлементСправочника[] элементы;
}
}

View File

@ -1,13 +0,0 @@
using System;
namespace Hcs.ClientApi.DataTypes
{
public class ГисЭлементСправочника
{
public string код;
public Guid гуид;
public bool актуальный;
public ГисПолеЭлементаСправочника[] поля;
public ГисЭлементСправочника[] элементы;
}
}

View File

@ -1,106 +0,0 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Hcs.ClientApi.DebtRequestsApi
{
public class HcsDebtRequestsApi
{
private HcsClientConfig config;
public HcsDebtRequestsApi(HcsClientConfig config)
{
this.config = config;
}
public async Task<HcsDebtSubrequest> ExportDSRByRequestNumber(
string requestNumber, CancellationToken token = default)
{
var worker = new HcsDebtSubrequestExporter(config);
return await worker.ExportDSRByRequestNumber(requestNumber, token);
}
/// <summary>
/// Получение списка запросов о наличии задолженности направленных в данный период
/// </summary>
public async Task<int> ExportDSRsByPeriodOfSending(
DateTime startDate,
DateTime endDate,
Guid? firstSubrequestGuid,
Action<HcsDebtSubrequest> resultHandler,
CancellationToken token = default)
{
var worker = new HcsDebtSubrequestExporter(config);
return await worker.ExportDSRsByPeriodOfSending(
startDate, endDate, firstSubrequestGuid, resultHandler, token);
}
/// <summary>
/// Отправка пакета ответов на запросы о наличии задолженности
/// </summary>
public async Task<int> ImportDSRsResponsesAsOneBatch(
HcsDebtResponse[] responses,
Action<HcsDebtResponse, HcsDebtResponseResult> resultHandler,
CancellationToken token = default)
{
var worker = new HcsDebtResponseImporter(config);
var results = await worker.ImportDSRResponses(responses, token);
foreach (var response in responses)
{
var result = results.FirstOrDefault(
x => x.SubrequestGuid == response.SubrequestGuid &&
x.TransportGuid == response.TransportGuid);
if (result == null)
{
result = new HcsDebtResponseResult();
result.TransportGuid = response.TransportGuid;
result.SubrequestGuid = response.SubrequestGuid;
result.Error = new HcsException(
$"В пакете результатов приема ответов нет" +
$" результата для подзапроса {response.SubrequestGuid}");
}
resultHandler(response, result);
}
return responses.Length;
}
/// <summary>
/// Отправка ответов на запросы о наличии задолженности для списков любой длины
/// </summary>
public async Task<int> ImportDSRsResponses(
HcsDebtResponse[] responses,
Action<HcsDebtResponse, HcsDebtResponseResult> resultHandler,
CancellationToken token = default)
{
int chunkSize = 20;
int i = 0;
HcsDebtResponse[][] chunks =
responses.GroupBy(s => i++ / chunkSize).Select(g => g.ToArray()).ToArray();
int n = 0;
foreach (var chunk in chunks)
{
n += await ImportDSRsResponsesAsOneBatch(chunk, resultHandler, token);
}
return n;
}
/// <summary>
/// Отправка ответа на один запрос о наличии задолженности
/// </summary>
public async Task<HcsDebtResponseResult> ImportDSRResponse(
HcsDebtResponse response, CancellationToken token = default)
{
HcsDebtResponse[] array = { response };
HcsDebtResponseResult result = null;
await ImportDSRsResponses(array, (x, y) => result = y, token);
return result;
}
}
}

View File

@ -1,135 +0,0 @@
using Hcs.ClientApi.RemoteCaller;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DebtRequests = Hcs.Service.Async.DebtRequests.v15_7_0_1;
namespace Hcs.Service.Async.DebtRequests.v15_7_0_1
{
public partial class AckRequestAck : IHcsAck { }
public partial class getStateResult : IHcsGetStateResultMany { }
public partial class Fault : IHcsFault { }
public partial class HeaderType : IHcsHeaderType { }
}
namespace Hcs.ClientApi.DebtRequestsApi
{
/// Метод для отправки запросов к сервису запросов о наличии задолженности
/// Описание: http://open-gkh.ru/DebtRequestsServiceAsync/
public class HcsDebtRequestsMethod : HcsRemoteCallMethod<IHcsGetStateResultMany>
{
public HcsEndPoints EndPoint => HcsEndPoints.DebtRequestsAsync;
public HcsDebtRequestsMethod(HcsClientConfig config) : base(config)
{
}
public DebtRequests.RequestHeader CreateRequestHeader() =>
HcsRequestHelper.CreateHeader<DebtRequests.RequestHeader>(ClientConfig);
public System.ServiceModel.EndpointAddress RemoteAddress
=> GetEndpointAddress(HcsConstants.EndPointLocator.GetPath(EndPoint));
private DebtRequests.DebtRequestsAsyncPortClient NewPortClient()
{
var client = new DebtRequests.DebtRequestsAsyncPortClient(_binding, RemoteAddress);
ConfigureEndpointCredentials(client.Endpoint, client.ClientCredentials);
return client;
}
/// <summary>
/// Метод отправления запроса
/// </summary>
public async Task<IHcsAck> SendAsync(object request, CancellationToken token)
{
Func<Task<IHcsAck>> func = async () => await SendBareAsync(request);
return await RunRepeatableTaskInsistentlyAsync(func, token);
}
private async Task<IHcsAck> SendBareAsync(object request)
{
if (request == null) throw new ArgumentNullException("Null request");
string version = HcsRequestHelper.GetRequestVersionString(request);
_config.Log($"Отправляю {RemoteAddress.Uri}/{request.GetType().Name}" +
$" в версии {version} {ThreadIdText}...");
IHcsAck ack;
using (var client = NewPortClient())
{
switch (request)
{
case DebtRequests.exportDebtSubrequestsRequest x:
{
var response = await client.exportDebtSubrequestsAsync(x.RequestHeader, x.exportDSRsRequest);
ack = response.AckRequest.Ack;
break;
}
case DebtRequests.importResponsesRequest x:
{
var response = await client.importResponsesAsync(x.RequestHeader, x.importDSRResponsesRequest);
ack = response.AckRequest.Ack;
break;
}
default:
throw new HcsException($"Неизвестный тип запроса: {request.GetType().Name}");
}
}
_config.Log($"Запрос принят в обработку, подтверждение {ack.MessageGUID}");
return ack;
}
/// <summary>
/// Выполняет однократную проверку наличия результата.
/// Возвращает null если результата еще нет.
/// </summary>
protected override async Task<IHcsGetStateResultMany> TryGetResultAsync(
IHcsAck sourceAck, CancellationToken token = default)
{
Func<Task<IHcsGetStateResultMany>> func = async () => await TryGetResultBareAsync(sourceAck);
return await RunRepeatableTaskInsistentlyAsync(func, token);
}
private async Task<IHcsGetStateResultMany> TryGetResultBareAsync(IHcsAck sourceAck)
{
using (var client = NewPortClient())
{
var requestHeader = HcsRequestHelper.CreateHeader<DebtRequests.RequestHeader>(_config);
var requestBody = new DebtRequests.getStateRequest { MessageGUID = sourceAck.MessageGUID };
var response = await client.getStateAsync(requestHeader, requestBody);
var resultBody = response.getStateResult;
if (resultBody.RequestState == HcsAsyncRequestStateTypes.Ready)
{
CheckResultForErrors(resultBody);
return resultBody;
}
return null;
}
}
private void CheckResultForErrors(IHcsGetStateResultMany result)
{
if (result == null) throw new HcsException("Пустой result");
if (result.Items == null) throw new HcsException("Пустой result.Items");
result.Items.OfType<DebtRequests.Fault>().ToList().ForEach(x =>
{
throw HcsRemoteException.CreateNew(x.ErrorCode, x.ErrorMessage);
});
result.Items.OfType<DebtRequests.ErrorMessageType>().ToList().ForEach(x =>
{
throw HcsRemoteException.CreateNew(x.ErrorCode, x.Description);
});
}
}
}

View File

@ -1,40 +0,0 @@
using System;
namespace Hcs.ClientApi.DebtRequestsApi
{
/// <summary>
/// Ответ на запрос о наличии задолженности
/// </summary>
public class HcsDebtResponse
{
// Добавить в XML-описание
public Guid TransportGuid; // Идентификатор ответа в отправляющей системе
public Guid SubrequestGuid; // Идентификатор подзапроса
public bool HasDebt;
public HcsPersonalData[] PersonalData;
public string Description;
}
/// <summary>
/// Сведения о должнике
/// </summary>
public class HcsPersonalData
{
public string FirstName;
public string MiddleName;
public string LastName;
}
/// <summary>
/// Результат отправки ответа на запрос о наличии задолженности
/// </summary>
public class HcsDebtResponseResult
{
// Добавить в XML-описание
public Guid TransportGuid; // Идентификатор ответа в отправляющей системе
public Guid SubrequestGuid; // Идентификатор подзапроса
public Exception Error; // Ожибка отправки если указано
public DateTime UpdateDate; // Дата успешного приема ответа если не указана ошибка
public bool HasError => (Error != null);
}
}

View File

@ -1,141 +0,0 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DebtRequests = Hcs.Service.Async.DebtRequests.v15_7_0_1;
namespace Hcs.ClientApi.DebtRequestsApi
{
public class HcsDebtResponseImporter : HcsDebtRequestsMethod
{
public HcsDebtResponseImporter(HcsClientConfig config) : base(config)
{
}
public async Task<HcsDebtResponseResult[]> ImportDSRResponses(
HcsDebtResponse[] debtResponses, CancellationToken token = default)
{
if (debtResponses == null || debtResponses.Length == 0)
throw new ArgumentException("Пустой debtResponses");
var actions = debtResponses.Select(x => ConvertToImportAction(x)).ToArray();
var requestHeader = CreateRequestHeader();
var requestBody = new DebtRequests.importDSRResponsesRequest
{
Id = HcsConstants.SignedXmlElementId,
// TODO: Проверить комментарий
// Версия предустановлена в WSDL, реальная версия шаблонов дает ошибку "Bad Request"
//version = HcsConstants.DefaultHCSVersionString,
action = actions
};
var request = new DebtRequests.importResponsesRequest
{
RequestHeader = requestHeader,
importDSRResponsesRequest = requestBody
};
var ack = await SendAsync(request, token);
var result = await WaitForResultAsync(ack, true, token);
var responseResults = result.Items.Select(
x => ParseDebtResponseResultSafely(x)).ToArray();
if (debtResponses.Length != responseResults.Length)
throw new HcsException(
$"Количество направленных ответов {debtResponses.Length} не совпадает" +
$" с количеством {responseResults.Length} результатов обработки");
foreach (var response in debtResponses)
{
var found = responseResults.FirstOrDefault(x => x.TransportGuid == response.TransportGuid);
if (found != null) found.SubrequestGuid = response.SubrequestGuid;
}
return responseResults;
}
private DebtRequests.importDSRResponsesRequestAction ConvertToImportAction(
HcsDebtResponse source)
{
DebtRequests.DebtInfoType[] debtInfo = null;
if (source.HasDebt)
{
if (IsArrayEmpty(source.PersonalData)) throw new HcsException("Не указаны должники");
debtInfo = source.PersonalData.Select(x => new DebtRequests.DebtInfoType
{
person = new DebtRequests.DebtInfoTypePerson
{
firstName = x.FirstName,
lastName = x.LastName,
middleName = x.MiddleName
}
}).ToArray();
}
var responseData = new DebtRequests.ImportDSRResponseType()
{
hasDebt = source.HasDebt,
description = source.Description,
Items = debtInfo,
// TODO: Проверить комментарий
//debtInfo = debtInfo, // Так было в hcs-v13
executorGUID = ClientConfig.ExecutorGUID
};
return new DebtRequests.importDSRResponsesRequestAction()
{
subrequestGUID = source.SubrequestGuid.ToString(),
TransportGUID = source.TransportGuid.ToString(),
actionType = DebtRequests.DSRResponseActionType.Send,
responseData = responseData
};
}
private HcsDebtResponseResult ParseDebtResponseResultSafely(object resultItem)
{
try
{
return ParseDebtResponseResult(resultItem);
}
catch (Exception e)
{
return new HcsDebtResponseResult() { Error = e };
}
}
private HcsDebtResponseResult ParseDebtResponseResult(object resultItem)
{
if (resultItem == null) throw new HcsException("Пустой resultItem");
var common = resultItem as DebtRequests.CommonResultType;
if (common == null) throw new HcsException($"Неожиданный тип экземпляра ответа {resultItem.GetType()}");
if (common.Items == null || common.Items.Length == 0)
throw new HcsException("Пустой набор common.Items");
var result = new HcsDebtResponseResult();
foreach (var commonItem in common.Items)
{
if (commonItem == null) throw new HcsException("Пустой commonItem");
switch (commonItem)
{
case DebtRequests.CommonResultTypeError error:
result.Error = new HcsRemoteException(error.ErrorCode, error.Description);
break;
case DateTime updateDate:
result.UpdateDate = updateDate;
break;
default:
throw new HcsException($"Неожиданный тип сommonItem" + commonItem.GetType());
}
}
result.TransportGuid = ParseGuid(common.TransportGUID);
return result;
}
}
}

View File

@ -1,39 +0,0 @@
using System;
namespace Hcs.ClientApi.DebtRequestsApi
{
/// <summary>
/// Подзапрос о наличии задолженности за ЖКУ у организаци предоставляющей ЖКУ.
/// В терминологии ГИСЖКХ это называется Subrequests, потому что сама ГИСЖКХ выбирает организации,
/// которым (пере)направляется оригинальный запрос о наличии задолженности направленный его источником
/// в ГИСЖКХ.
/// </summary>
public class HcsDebtSubrequest
{
public enum ResponseStatusType { Sent, NotSent, AutoGenerated }
// TODO: Добавить XML-описания
public Guid SubrequestGuid; // Идентификатор подзапроса направленный конкретному поставщику ЖКУ
public Guid RequestGuid; // Идентификатор первичного запроса направленного соццентром всем поставщикам
public string RequestNumber; // Номер запроса
public DateTime SentDate; // Дата направления
public string Address; // Строка адреса из запроса
public Guid FiasHouseGuid; // Идентификатор здания в ФИАС
public Guid GisHouseGuid; // Идентификатор здания в ГИСЖКХ
public Guid HМObjectGuid; // Идентификатор помещения в ГИСЖКХ (v14)
public string HMObjectType; // Тип помещения (v14)
public string AddressDetails; // Номер помещения (не заполняется в v14)
public DateTime DebtStartDate; // Начало периода задолженности
public DateTime DebtEndDate; // Конец периода задолженности
public ResponseStatusType ResponseStatus; // Признак отправления запроса
public DateTime ResponseDate; // Дата ответа
public override string ToString()
{
return
$"ПодзапросОНЗ #{RequestNumber}" +
$" Address=[{Address}] Details=[{AddressDetails}]" +
$" HMO={HМObjectGuid} Sent={SentDate} ResponseStatus={ResponseStatus}";
}
}
}

View File

@ -1,251 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DebtRequests = Hcs.Service.Async.DebtRequests.v15_7_0_1;
namespace Hcs.ClientApi.DebtRequestsApi
{
/// <summary>
/// Метод получения данных о направленных нам (под)запросах о наличии задолженности
/// </summary>
public class HcsDebtSubrequestExporter : HcsDebtRequestsMethod
{
public HcsDebtSubrequestExporter(HcsClientConfig config) : base(config)
{
EnableMinimalResponseWaitDelay = true;
}
public class DSRsBatch
{
public List<HcsDebtSubrequest> DebtSubrequests = new List<HcsDebtSubrequest>();
public Guid NextSubrequestGuid;
public bool LastPage;
}
public async Task<HcsDebtSubrequest> ExportDSRByRequestNumber(string requestNumber, CancellationToken token)
{
var conditionTypes = new List<DebtRequests.ItemsChoiceType5>();
var conditionValues = new List<object>();
conditionTypes.Add(DebtRequests.ItemsChoiceType5.requestNumber);
conditionValues.Add(requestNumber);
var result = await ExportSubrequestBatchByCondition(
conditionTypes.ToArray(), conditionValues.ToArray(), token);
int n = result.DebtSubrequests.Count;
if (n == 0) return null;
if (n == 1) return result.DebtSubrequests[0];
throw new HcsException(
$"По номеру запроса о наличии задолженности №{requestNumber}" +
$" получено несколько ({n}) ответов, ожидался только один");
}
public async Task<int> ExportDSRsByPeriodOfSending(
DateTime startDate, DateTime endDate, Guid? firstSubrequestGuid,
Action<HcsDebtSubrequest> resultHandler, CancellationToken token = default)
{
int numResults = 0;
Guid? nextSubrequestGuid = firstSubrequestGuid;
bool firstGuidIsReliable = false;
while (true)
{
if (numResults == 0) Log("Запрашиваем первую партию записей...");
else Log($"Запрашиваем следующую партию записей, уже получено {numResults}...");
var batch = await ExportDSRsBatchByPeriodOfSending(
startDate, endDate, nextSubrequestGuid, token, firstGuidIsReliable);
foreach (var s in batch.DebtSubrequests)
{
if (resultHandler != null) resultHandler(s);
numResults += 1;
}
if (batch.LastPage) break;
nextSubrequestGuid = batch.NextSubrequestGuid;
firstGuidIsReliable = true;
}
return numResults;
}
public async Task<DSRsBatch> ExportDSRsBatchByPeriodOfSending(
DateTime startDate, DateTime endDate, Guid? firstSubrequestGuid,
CancellationToken token, bool firstGuidIsReliable)
{
var conditionTypes = new List<DebtRequests.ItemsChoiceType5>();
var conditionValues = new List<object>();
conditionTypes.Add(DebtRequests.ItemsChoiceType5.periodOfSendingRequest);
conditionValues.Add(new DebtRequests.Period() { startDate = startDate, endDate = endDate });
if (firstSubrequestGuid != null)
{
conditionTypes.Add(DebtRequests.ItemsChoiceType5.exportSubrequestGUID);
conditionValues.Add(firstSubrequestGuid.ToString());
}
Func<Task<DSRsBatch>> taskFunc = async ()
=> await ExportSubrequestBatchByCondition(
conditionTypes.ToArray(), conditionValues.ToArray(), token);
Func<Exception, bool> canIgnoreFunc = delegate (Exception e)
{
return CanIgnoreSuchException(e, firstGuidIsReliable);
};
return await RunRepeatableTaskAsync(taskFunc, canIgnoreFunc, int.MaxValue);
}
private async Task<DSRsBatch> ExportSubrequestBatchByCondition(
DebtRequests.ItemsChoiceType5[] conditionTypes, object[] conditionValues,
CancellationToken token)
{
var requestHeader = CreateRequestHeader();
var requestBody = new DebtRequests.exportDSRsRequest
{
Id = HcsConstants.SignedXmlElementId,
// TODO: Тут напрямую указывается версия
version = "14.0.0.0",
ItemsElementName = conditionTypes,
Items = conditionValues
};
var request = new DebtRequests.exportDebtSubrequestsRequest
{
RequestHeader = requestHeader,
exportDSRsRequest = requestBody
};
var ack = await SendAsync(request, token);
try
{
var result = await WaitForResultAsync(ack, true, token);
return ParseExportResultBatch(result);
}
catch (HcsNoResultsRemoteException)
{
return new DSRsBatch() { LastPage = true };
}
}
private DSRsBatch ParseExportResultBatch(RemoteCaller.IHcsGetStateResultMany result)
{
var batch = new DSRsBatch();
result.Items.OfType<DebtRequests.exportDSRsResultType>().ToList().ForEach(r =>
{
Log($"Принято запросов о наличии задолженности: {r.subrequestData?.Count()}");
// на последней странице вывода может не быть ни одной записи
if (r.subrequestData != null)
{
r.subrequestData.ToList().ForEach(s => { batch.DebtSubrequests.Add(Adapt(s)); });
}
if (r.pagedOutput == null || r.pagedOutput.Item == null) batch.LastPage = true;
else
{
var item = r.pagedOutput.Item;
if (item is bool && (bool)item == true) batch.LastPage = true;
else if (!Guid.TryParse(item.ToString(), out batch.NextSubrequestGuid))
throw new HcsException($"Неожиданное значение pagedOutput [{item}]");
}
});
return batch;
}
private HcsDebtSubrequest Adapt(DebtRequests.DSRType s)
{
var dsr = new HcsDebtSubrequest();
dsr.SubrequestGuid = ParseGuid(s.subrequestGUID);
dsr.RequestGuid = ParseGuid(s.requestInfo.requestGUID);
dsr.RequestNumber = s.requestInfo.requestNumber;
dsr.SentDate = s.requestInfo.sentDate;
dsr.Address = s.requestInfo.housingFundObject.address;
var hfo = s.requestInfo.housingFundObject;
if (hfo.Items != null &&
hfo.ItemsElementName != null &&
hfo.Items.Length == hfo.ItemsElementName.Length)
{
for (int i = 0; i < hfo.Items.Length; i++)
{
string itemValue = hfo.Items[i];
switch (hfo.ItemsElementName[i])
{
case DebtRequests.ItemsChoiceType7.HMobjectGUID:
dsr.HМObjectGuid = ParseGuid(itemValue);
break;
case DebtRequests.ItemsChoiceType7.houseGUID:
dsr.GisHouseGuid = ParseGuid(itemValue);
break;
case DebtRequests.ItemsChoiceType7.adressType:
dsr.HMObjectType = itemValue;
break;
case DebtRequests.ItemsChoiceType7.addressDetails:
dsr.AddressDetails = itemValue;
break;
}
}
}
if (!string.IsNullOrEmpty(hfo.fiasHouseGUID))
{
dsr.FiasHouseGuid = ParseGuid(hfo.fiasHouseGUID);
}
// TODO: Проверить комментарий
// Из hcs-v13
//dsr.GisHouseGuid = ParseGuid(s.requestInfo.housingFundObject.houseGUID);
//dsr.AddressDetails = s.requestInfo.housingFundObject.addressDetails;
dsr.DebtStartDate = s.requestInfo.period.startDate;
dsr.DebtEndDate = s.requestInfo.period.endDate;
dsr.ResponseStatus = ConvertStatusType(s.responseStatus);
dsr.ResponseDate = s.requestInfo.responseDate;
return dsr;
}
private HcsDebtSubrequest.ResponseStatusType ConvertStatusType(DebtRequests.ResponseStatusType type)
{
switch (type)
{
case DebtRequests.ResponseStatusType.Sent: return HcsDebtSubrequest.ResponseStatusType.Sent;
case DebtRequests.ResponseStatusType.NotSent: return HcsDebtSubrequest.ResponseStatusType.NotSent;
case DebtRequests.ResponseStatusType.AutoGenerated: return HcsDebtSubrequest.ResponseStatusType.AutoGenerated;
default: throw new HcsException("Неизвестный статус отправки ответа: " + type);
}
}
// TODO: Проверить игнорирование ошибок
private bool CanIgnoreSuchException(Exception e, bool firstGuidIsReliable)
{
// "Произошла ошибка при передаче данных. Попробуйте осуществить передачу данных повторно."
if (HcsUtil.EnumerateInnerExceptions(e).Any(
x => x is HcsRemoteException && (x as HcsRemoteException).ErrorCode == "EXP001000"))
{
return true;
}
// Возникающий на больших списках отказ возобновляемый, учитывем факт что GUID был
// получен из ГИСЖКХ и явно является надежным
if (firstGuidIsReliable && HcsUtil.EnumerateInnerExceptions(e).Any(
x => x.Message != null && x.Message.Contains("Error loading content: Content not found for guid:")))
{
return true;
}
return false;
}
}
}

View File

@ -1,27 +0,0 @@
using Hcs.ClientApi.DataTypes;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Hcs.ClientApi.DeviceMeteringApi
{
/// <summary>
/// Методы ГИС ЖКХ сервиса hcs-device-metering (показания приборов учета)
/// </summary>
public class HcsDeviceMeteringApi
{
public HcsClientConfig Config { get; private set; }
public HcsDeviceMeteringApi(HcsClientConfig config)
{
this.Config = config;
}
public async Task<DateTime> РазместитьПоказания(
ГисПриборУчета прибор, ГисПоказания показания, CancellationToken token = default)
{
var method = new HcsMethodImportMeteringDevicesValues(Config);
return await method.ImportMeteringDevicesValues(прибор, показания, token);
}
}
}

View File

@ -1,118 +0,0 @@
using Hcs.ClientApi.RemoteCaller;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DeviceMetering = Hcs.Service.Async.DeviceMetering.v15_7_0_1;
namespace Hcs.Service.Async.DeviceMetering.v15_7_0_1
{
public partial class AckRequestAck : IHcsAck { }
public partial class getStateResult : IHcsGetStateResultMany { }
public partial class Fault : IHcsFault { }
public partial class HeaderType : IHcsHeaderType { }
}
namespace Hcs.ClientApi.DeviceMeteringApi
{
public class HcsDeviceMeteringMethod : HcsRemoteCallMethod<IHcsGetStateResultMany>
{
public HcsEndPoints EndPoint => HcsEndPoints.DeviceMeteringAsync;
public DeviceMetering.RequestHeader CreateRequestHeader() =>
HcsRequestHelper.CreateHeader<DeviceMetering.RequestHeader>(ClientConfig);
public HcsDeviceMeteringMethod(HcsClientConfig config) : base(config) { }
public System.ServiceModel.EndpointAddress RemoteAddress
=> GetEndpointAddress(HcsConstants.EndPointLocator.GetPath(EndPoint));
private DeviceMetering.DeviceMeteringPortTypesAsyncClient NewPortClient()
{
var client = new DeviceMetering.DeviceMeteringPortTypesAsyncClient(_binding, RemoteAddress);
ConfigureEndpointCredentials(client.Endpoint, client.ClientCredentials);
return client;
}
public async Task<IHcsGetStateResultMany> SendAndWaitResultAsync(
object request,
Func<DeviceMetering.DeviceMeteringPortTypesAsyncClient, Task<IHcsAck>> sender,
CancellationToken token)
{
while (true)
{
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<IHcsGetStateResultMany> SendAndWaitResultAsyncImpl(
object request,
Func<DeviceMetering.DeviceMeteringPortTypesAsyncClient, 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<DeviceMetering.ErrorMessageType>().ToList().ForEach(x =>
{
throw HcsRemoteException.CreateNew(x.ErrorCode, x.Description);
});
return stateResult;
}
/// <summary>
/// Выполняет однократную проверку наличия результата.
/// Возвращает null если результата еще нет.
/// </summary>
protected override async Task<IHcsGetStateResultMany> TryGetResultAsync(IHcsAck sourceAck, CancellationToken token)
{
using (var client = NewPortClient())
{
var requestHeader = HcsRequestHelper.CreateHeader<DeviceMetering.RequestHeader>(_config);
var requestBody = new DeviceMetering.getStateRequest { MessageGUID = sourceAck.MessageGUID };
var response = await client.getStateAsync(requestHeader, requestBody);
var resultBody = response.getStateResult;
if (resultBody.RequestState == HcsAsyncRequestStateTypes.Ready)
{
return resultBody;
}
return null;
}
}
}
}

View File

@ -1,22 +0,0 @@
using System.Text.RegularExpressions;
namespace Hcs.ClientApi.DeviceMeteringApi
{
public class HcsDeviceMeteringUtil
{
public static string ConvertMeterReading(string reading, bool isRequired)
{
if (string.IsNullOrEmpty(reading)) return (isRequired ? "0" : null);
// TODO: Проверить комментарий
// Исправляем типичный отказ ГИС в приеме показаний: заменяем запятую на точку
string betterReading = reading.Contains(",") ? reading.Replace(",", ".") : reading;
// Шаблон из: http://open-gkh.ru/MeteringDeviceBase/MeteringValueType.html
var match = Regex.Match(betterReading, "^\\d{1,15}(\\.\\d{1,7})?$");
if (match.Success) return betterReading;
throw new HcsException($"Значение показания \"{reading}\" не соответствует требованиям ГИС: N.N");
}
}
}

View File

@ -1,76 +0,0 @@
using Hcs.ClientApi.DataTypes;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DeviceMetering = Hcs.Service.Async.DeviceMetering.v15_7_0_1;
namespace Hcs.ClientApi.DeviceMeteringApi
{
/// <summary>
/// Размещение в ГИС показаний прибора учета
/// http://open-gkh.ru/DeviceMetering/importMeteringDeviceValuesRequest.html
/// </summary>
public class HcsMethodImportMeteringDevicesValues : HcsDeviceMeteringMethod
{
public HcsMethodImportMeteringDevicesValues(HcsClientConfig config) : base(config)
{
CanBeRestarted = false;
}
public async Task<DateTime> ImportMeteringDevicesValues(
ГисПриборУчета прибор, ГисПоказания показания, CancellationToken token)
{
if (прибор == null) throw new ArgumentNullException(nameof(прибор));
if (показания == null) throw new ArgumentNullException(nameof(показания));
var current = new DeviceMetering.importMeteringDeviceValuesRequestMeteringDevicesValuesElectricDeviceValueCurrentValue()
{
TransportGUID = FormatGuid(Guid.NewGuid()),
DateValue = показания.ДатаСнятия,
MeteringValueT1 = HcsDeviceMeteringUtil.ConvertMeterReading(показания.ПоказанияТ1, false),
MeteringValueT2 = HcsDeviceMeteringUtil.ConvertMeterReading(показания.ПоказанияТ2, false),
MeteringValueT3 = HcsDeviceMeteringUtil.ConvertMeterReading(показания.ПоказанияТ3, false)
};
var electric = new DeviceMetering.importMeteringDeviceValuesRequestMeteringDevicesValuesElectricDeviceValue()
{
CurrentValue = current
};
var value = new DeviceMetering.importMeteringDeviceValuesRequestMeteringDevicesValues()
{
ItemElementName = DeviceMetering.ItemChoiceType.MeteringDeviceRootGUID,
Item = FormatGuid(прибор.ГуидПрибораУчета),
Item1 = electric
};
var request = new DeviceMetering.importMeteringDeviceValuesRequest()
{
Id = HcsConstants.SignedXmlElementId,
MeteringDevicesValues = [value]
};
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
{
var ackResponse = await portClient.importMeteringDeviceValuesAsync(
CreateRequestHeader(), request);
return ackResponse.AckRequest.Ack;
}, token);
if (IsArrayEmpty(stateResult.Items)) throw new HcsException("Пустой stateResult.Items");
stateResult.Items.OfType<DeviceMetering.CommonResultTypeError>().ToList()
.ForEach(error => { throw HcsRemoteException.CreateNew(error.ErrorCode, error.Description); });
var commonResult = RequireSingleItem<DeviceMetering.CommonResultType>(stateResult.Items);
if (IsArrayEmpty(commonResult.Items)) throw new HcsException("Пустой commonResult.Items");
DateTime датаПриема = commonResult.Items.OfType<DateTime>().FirstOrDefault();
if (датаПриема == default) throw new HcsException("Сервер не вернул дату приема им показаний");
return датаПриема;
}
}
}

View File

@ -1,394 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Hcs.ClientApi.FileStoreServiceApi
{
/// <summary>
/// Описание протокола в файле "ГИС ЖКХ. Альбом ТФФ 14.5.0.1.docx"
/// 2.5 Описание протокола обмена файлами с внешними системами
public class HcsFileStoreServiceApi
{
public HcsClientConfig Config { get; private set; }
/// <summary>
/// Максимальный размер в байтах части файла, которую разрешено
/// загружать на сервер по спецификации протокола
/// </summary>
private const int MAX_PART_LENGTH = 5242880;
public HcsFileStoreServiceApi(HcsClientConfig config)
{
this.Config = config;
}
/// <summary>
/// Путь к сервису хранения файлов ГИС ЖКХ на серевере API
/// </summary>
private const string ExtBusFileStoreServiceRest = "ext-bus-file-store-service/rest";
/// <summary>
/// Получение файла ранее загруженного в ГИС ЖКХ
/// </summary>
public async Task<HcsFile> DownloadFile(
Guid fileGuid, HcsFileStoreContext context, CancellationToken token)
{
long length = await GetFileLength(context, fileGuid, token);
if (length <= MAX_PART_LENGTH) return await DownloadSmallFile(fileGuid, context, token);
return await DownloadLargeFile(fileGuid, length, context, token);
}
/// <summary>
/// Получение файла по частям (не более 5Мб) по GUID файла
/// </summary>
private async Task<HcsFile> DownloadLargeFile(
Guid fileGuid, long fileSize, HcsFileStoreContext context, CancellationToken token)
{
if (fileSize <= MAX_PART_LENGTH)
throw new ArgumentException("Too short file for partial download");
string requestUri = ComposeFileDownloadUri(fileGuid, context);
var resultStream = new MemoryStream();
string resultContentType = null;
using (var client = BuildHttpClient())
{
long doneSize = 0;
while (doneSize < fileSize)
{
long remainderSize = fileSize - doneSize;
long partSize = Math.Min(remainderSize, MAX_PART_LENGTH);
long fromPosition = doneSize;
long toPosition = fromPosition + partSize - 1;
var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
request.Headers.Range = new RangeHeaderValue(fromPosition, toPosition);
var response = await SendRequestAsync(client, request, token);
resultContentType = response.Content.Headers.ContentType.ToString();
long? responseSize = response.Content.Headers.ContentLength;
if (responseSize == null || (long)responseSize != partSize)
throw new HcsException($"Получена часть файла длиной {responseSize}, а запрашивалась длина {partSize}");
using (var partStream = await response.Content.ReadAsStreamAsync())
{
partStream.Position = 0;
await partStream.CopyToAsync(resultStream);
}
doneSize += partSize;
}
resultStream.Position = 0;
return new HcsFile(null, resultContentType, resultStream);
}
}
private string ComposeFileDownloadUri(Guid fileGuid, HcsFileStoreContext context)
{
string endpointName = $"{ExtBusFileStoreServiceRest}/{context.GetName()}/{HcsUtil.FormatGuid(fileGuid)}?getfile";
return Config.ComposeEndpointUri(endpointName);
}
/// <summary>
/// Получение файла одной частью (не более 5Мб) по GUID файла
/// </summary>
private async Task<HcsFile> DownloadSmallFile(
Guid fileGuid, HcsFileStoreContext context, CancellationToken token)
{
string requestUri = ComposeFileDownloadUri(fileGuid, context);
using (var client = BuildHttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
var response = await SendRequestAsync(client, request, token);
return new HcsFile(
null,
response.Content.Headers.ContentType.ToString(),
await response.Content.ReadAsStreamAsync());
}
}
public async Task<Guid> UploadFile(HcsFile file, HcsFileStoreContext context, CancellationToken token)
{
if (file is null) throw new ArgumentNullException(nameof(file));
if (file.Length <= MAX_PART_LENGTH)
{
return await UploadSmallFile(file, context, token);
}
else
{
return await UploadLargeFile(file, context, token);
}
}
/// <summary>
/// Отправка большого файла по частям
/// </summary>
private async Task<Guid> UploadLargeFile(HcsFile file, HcsFileStoreContext context, CancellationToken token)
{
using var client = BuildHttpClient();
if (file.Length == 0) throw new ArgumentException("Нельзя передавать файл нулевой длины");
int numParts = (int)Math.Ceiling((double)file.Length / MAX_PART_LENGTH);
Config.Log($"Запрашиваю UploadID для большого файла {file.FileName}");
Guid uploadId = await QueryNewUploadId(client, context, file, numParts, token);
Config.Log($"Получил UploadID {uploadId} для отправки файла {file.FileName} размером {file.Length} байт");
long partOffset = 0;
for (int partNumber = 1; partNumber <= numParts; partNumber++)
{
long lengthLeft = file.Length - partOffset;
int partLength = (int)Math.Min(lengthLeft, MAX_PART_LENGTH);
var partStream = new HcsPartialStream(file.Stream, partOffset, partLength);
Config.Log($"Отправляю часть {partNumber}/{numParts} размером {partLength} байт для файла {file.FileName}");
await UploadFilePart(client, context, uploadId, partNumber, partStream, token);
partOffset += partLength;
}
Config.Log($"Отправляем признак завершения передачи файла {file.FileName}");
await CompleteUpload(client, context, uploadId, token);
Config.Log($"Файл {file.FileName} успешно передан, получен код файла {uploadId}");
return uploadId;
}
/// <summary>
/// Получение кода для загрузки большого файла из нескольких частей менее 5Мб
/// </summary>
private async Task<Guid> QueryNewUploadId(
HttpClient client, HcsFileStoreContext context, HcsFile file, int numParts, CancellationToken token)
{
string endpointName = $"{ExtBusFileStoreServiceRest}/{context.GetName()}/?upload";
string requestUri = Config.ComposeEndpointUri(endpointName);
var content = new StringContent("");
content.Headers.Add("X-Upload-Filename", CleanUploadFileName(file.FileName));
content.Headers.Add("X-Upload-Length", file.Length.ToString());
content.Headers.Add("X-Upload-Part-Count", numParts.ToString());
var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
request.Content = content;
var response = await SendRequestAsync(client, request, token);
return ParseUploadIdFromReponse(response);
}
private async Task UploadFilePart(
HttpClient client, HcsFileStoreContext context, Guid uploadId, int partNumber, Stream partStream,
CancellationToken token)
{
string endpointName = $"{ExtBusFileStoreServiceRest}/{context.GetName()}/{HcsUtil.FormatGuid(uploadId)}";
string requestUri = Config.ComposeEndpointUri(endpointName);
var content = new StreamContent(partStream);
content.Headers.Add("X-Upload-Partnumber", partNumber.ToString());
content.Headers.ContentMD5 = ComputeMD5(partStream);
var request = new HttpRequestMessage(HttpMethod.Put, requestUri);
request.Content = content;
await SendRequestAsync(client, request, token);
}
private async Task CompleteUpload(HttpClient client, HcsFileStoreContext context, Guid uploadId, CancellationToken token)
{
string endpointName = $"{ExtBusFileStoreServiceRest}/{context.GetName()}/{HcsUtil.FormatGuid(uploadId)}?completed";
string requestUri = Config.ComposeEndpointUri(endpointName);
var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
await SendRequestAsync(client, request, token);
}
/// <summary>
/// Загрузка в ГИС ЖКХ файла до 5Мб размером одной операцией
/// </summary>
private async Task<Guid> UploadSmallFile(HcsFile file, HcsFileStoreContext context, CancellationToken token)
{
using var client = BuildHttpClient();
string endpointName = $"{ExtBusFileStoreServiceRest}/{context.GetName()}";
string requestUri = Config.ComposeEndpointUri(endpointName);
Config.Log($"Начинаю upload малого файла [{file.FileName}] типа [{file.ContentType}] длиной {file.Length}");
if (file.Stream.Length != file.Length)
throw new HcsException($"Длина файла {file.Length} не соответствует размеру данных {file.Stream.Length}");
file.Stream.Position = 0;
var content = new StreamContent(file.Stream);
content.Headers.Add("X-Upload-Filename", CleanUploadFileName(file.FileName));
content.Headers.ContentMD5 = ComputeMD5(file.Stream);
var request = new HttpRequestMessage(HttpMethod.Put, requestUri);
request.Content = content;
var response = await SendRequestAsync(client, request, token);
return ParseUploadIdFromReponse(response);
}
/// <summary>
/// Получение информации о загружаемом или загруженном файле
/// </summary>
public async Task<long> GetFileLength(HcsFileStoreContext context, Guid fileId, CancellationToken token)
{
using var client = BuildHttpClient();
string endpointName = $"{ExtBusFileStoreServiceRest}/{context.GetName()}/{HcsUtil.FormatGuid(fileId)}";
string requestUri = Config.ComposeEndpointUri(endpointName);
var request = new HttpRequestMessage(HttpMethod.Head, requestUri);
var response = await SendRequestAsync(client, request, token);
long length = 0;
var lengthString = SearchResponseHeader(response, "X-Upload-Length");
if (!string.IsNullOrEmpty(lengthString) && long.TryParse(lengthString, out length)) return length;
throw new HcsException("В ответе сервера не указана длина файла");
}
/// <summary>
/// Возвращает вычисленное значение AttachmentHASH для данных файла @stream
/// </summary>
public string ComputeAttachmentHash(Stream stream)
{
var client = Config as HcsClient;
if (client == null) throw new HcsException("Не доступен объект HcsClient для вычиления AttachmentHASH");
// TODO: Проверить комментарий
// В декабре 2024 у меня сломалось вычисление AttachmentHASH для файлов, я стал вычислять
// явно верным алгоритмом ГОСТ94 для больших файлов уже неверное значение суммы. В январе
// 2025 путем перебора вариантов я обнаружил что ГИСЖКХ теперь вычисляет AttachmentHASH
// только по первой части большого файла.
//int hashSourceMaxLength = MAX_PART_LENGTH;
//if (stream.Length <= hashSourceMaxLength) return client.ComputeGost94Hash(stream);
//return client.ComputeGost94Hash(new HcsPartialStream(stream, 0, hashSourceMaxLength));
// 29.01.2025 СТП ГИС ЖКХ ответила что "проведены работы" и теперь
// я вижу что они снова вычисляют AttachmantHASH по полному файлу
return client.ComputeGost94Hash(stream);
}
private async Task<HttpResponseMessage> SendRequestAsync(
HttpClient client, HttpRequestMessage request, CancellationToken token)
{
token.ThrowIfCancellationRequested();
Config.Log($"Отправляю запрос {request.Method} \"{request.RequestUri}\"...");
var response = await client.SendAsync(request, token);
if (response.IsSuccessStatusCode) return response;
throw new HcsException(DescribeResponseError(response));
}
private Guid ParseUploadIdFromReponse(HttpResponseMessage response)
{
string uploadIdheaderName = "X-Upload-UploadID";
var uploadId = SearchResponseHeader(response, uploadIdheaderName);
if (uploadId != null) return HcsUtil.ParseGuid(uploadId);
throw new HcsException($"В ответе сервера нет заголовка {uploadIdheaderName}");
}
private HttpClient BuildHttpClient()
{
var _clientHandler = new HttpClientHandler();
_clientHandler.ClientCertificates.Add(Config.Certificate);
_clientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
var client = new HttpClient(_clientHandler);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("X-Upload-OrgPPAGUID", Config.OrgPPAGUID);
return client;
}
private string DescribeResponseError(HttpResponseMessage response)
{
string errorHeader = "X-Upload-Error";
var message = SearchResponseHeader(response, errorHeader);
if (message != null)
{
if (knownErrors.ContainsKey(message)) return $"{errorHeader}: {message} ({knownErrors[message]})";
return $"{errorHeader}: {message}";
}
return $"HTTP response status {response.StatusCode}";
}
private string SearchResponseHeader(HttpResponseMessage response, string headerName)
{
if (response.Headers.Any(x => x.Key == headerName))
{
var pair = response.Headers.First(x => x.Key == headerName);
if (pair.Value != null && pair.Value.Any())
{
return pair.Value.First();
}
}
return null;
}
private static Dictionary<string, string> knownErrors = new Dictionary<string, string>() {
{ "FieldValidationException", "не пройдены проверки на корректность заполнения полей (обязательность, формат и т.п.)" },
{ "FileNotFoundException", "не пройдены проверки на существование файла" },
{ "InvalidStatusException", "не пройдены проверки на корректный статус файла" },
{ "InvalidSizeException", "некорректный запрашиваемый размер файла" },
{ "FileVirusInfectionException", "содержимое файла инфицировано" },
{ "FileVirusNotCheckedException", "проверка на вредоносное содержимое не выполнялась" },
{ "FilePermissionException", "организация и внешняя система не имеют полномочий на скачивание файла" },
{ "DataProviderValidationException", "поставщик данных не найден, заблокирован или неактивен" },
{ "CertificateValidationException", "информационная система не найдена по отпечатку или заблокирована" },
{ "HashConflictException", "не пройдены проверки на соответствие контрольной сумме" },
{ "InvalidPartNumberException", "не пройдены проверки на номер части (номер превышает количество частей, указанных в инициализации)" },
{ "ContextNotFoundException", "неверное имя хранилища файлов" },
{ "ExtensionException", "недопустимое расширение файла" },
{ "DetectionException", "не удалось определить MIME-тип загружаемого файла" },
{ "INT002029", "сервис недоступен: выполняются регламентные работы" }
};
private byte[] ComputeMD5(System.IO.Stream stream)
{
var position = stream.Position;
var md5 = System.Security.Cryptography.MD5.Create().ComputeHash(stream);
stream.Position = position;
return md5;
}
/// <summary>
/// Готовит имя размещаемого файла для помещения в заголовок HTTP-запроса
/// </summary>
private string CleanUploadFileName(string fileName)
{
if (fileName is null) return null;
string bannedSymbols = "<>?:|*%\\\"";
var buf = new StringBuilder();
foreach (char ch in fileName)
{
if (bannedSymbols.Contains(ch)) buf.Append('_');
else buf.Append(ch);
}
// Спецификация предписывает кодировать имя файла по стандарту MIME RFC2047
// https://datatracker.ietf.org/doc/html/rfc2047
// Как имя кодировки можно явно использовать константу "windows-1251".
string characterSet = Encoding.Default.WebName;
return EncodedWord.RFC2047.Encode(
buf.ToString(), EncodedWord.RFC2047.ContentEncoding.Base64, characterSet);
}
}
}

View File

@ -1,374 +0,0 @@
//===============================================================================
// RFC2047 (Encoded Word) Decoder
// https://github.com/grumpydev/RFC2047-Encoded-Word-Encoder-Decoder/blob/master/EncodedWord/RFC2047.cs
// http://tools.ietf.org/html/rfc2047
//===============================================================================
// Copyright © Steven Robbins. All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
namespace EncodedWord
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
/// <summary>
/// Provides support for decoding RFC2047 (Encoded Word) encoded text
/// </summary>
public static class RFC2047
{
/// <summary>
/// Regex for parsing encoded word sections
/// From http://tools.ietf.org/html/rfc2047#section-3
/// encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
/// </summary>
private static readonly Regex EncodedWordFormatRegEx = new Regex(@"=\?(?<charset>.*?)\?(?<encoding>[qQbB])\?(?<encodedtext>.*?)\?=", RegexOptions.Singleline | RegexOptions.Compiled);
/// <summary>
/// Regex for removing CRLF SPACE separators from between encoded words
/// </summary>
private static readonly Regex EncodedWordSeparatorRegEx = new Regex(@"\?=\r\n =\?", RegexOptions.Compiled);
/// <summary>
/// Replacement string for removing CRLF SPACE separators
/// </summary>
private const string SeparatorReplacement = @"?==?";
/// <summary>
/// The maximum line length allowed
/// </summary>
private const int MaxLineLength = 75;
/// <summary>
/// Regex for "Q-Encoding" hex bytes from http://tools.ietf.org/html/rfc2047#section-4.2
/// </summary>
private static readonly Regex QEncodingHexCodeRegEx = new Regex(@"(=(?<hexcode>[0-9a-fA-F][0-9a-fA-F]))", RegexOptions.Compiled);
/// <summary>
/// Regex for replacing _ with space as declared in http://tools.ietf.org/html/rfc2047#section-4.2
/// </summary>
private static readonly Regex QEncodingSpaceRegEx = new Regex("_", RegexOptions.Compiled);
/// <summary>
/// Format for an encoded string
/// </summary>
private const string EncodedStringFormat = @"=?{0}?{1}?{2}?=";
/// <summary>
/// Special characters, as defined by RFC2047
/// </summary>
private static readonly char[] SpecialCharacters = { '(', ')', '<', '>', '@', ',', ';', ':', '<', '>', '/', '[', ']', '?', '.', '=', '\t' };
/// <summary>
/// Represents a content encoding type defined in RFC2047
/// </summary>
public enum ContentEncoding
{
/// <summary>
/// Unknown / invalid encoding
/// </summary>
Unknown,
/// <summary>
/// "Q Encoding" (reduced character set) encoding
/// http://tools.ietf.org/html/rfc2047#section-4.2
/// </summary>
QEncoding,
/// <summary>
/// Base 64 encoding
/// http://tools.ietf.org/html/rfc2047#section-4.1
/// </summary>
Base64
}
/// <summary>
/// Encode a string into RFC2047
/// </summary>
/// <param name="plainString">Plain string to encode</param>
/// <param name="contentEncoding">Content encoding to use</param>
/// <param name="characterSet">Character set used by plainString</param>
/// <returns>Encoded string</returns>
public static string Encode(string plainString, ContentEncoding contentEncoding = ContentEncoding.QEncoding, string characterSet = "iso-8859-1")
{
if (String.IsNullOrEmpty(plainString))
{
return String.Empty;
}
if (contentEncoding == ContentEncoding.Unknown)
{
throw new ArgumentException("contentEncoding cannot be unknown for encoding.", "contentEncoding");
}
if (!IsSupportedCharacterSet(characterSet))
{
throw new ArgumentException("characterSet is not supported", "characterSet");
}
var textEncoding = Encoding.GetEncoding(characterSet);
var encoder = GetContentEncoder(contentEncoding);
var encodedContent = encoder.Invoke(plainString, textEncoding);
return BuildEncodedString(characterSet, contentEncoding, encodedContent);
}
/// <summary>
/// Decode a string containing RFC2047 encoded sections
/// </summary>
/// <param name="encodedString">String contaning encoded sections</param>
/// <returns>Decoded string</returns>
public static string Decode(string encodedString)
{
// Remove separators
var decodedString = EncodedWordSeparatorRegEx.Replace(encodedString, SeparatorReplacement);
return EncodedWordFormatRegEx.Replace(
decodedString,
m =>
{
var contentEncoding = GetContentEncodingType(m.Groups["encoding"].Value);
if (contentEncoding == ContentEncoding.Unknown)
{
// Regex should never match, but return anyway
return string.Empty;
}
var characterSet = m.Groups["charset"].Value;
if (!IsSupportedCharacterSet(characterSet))
{
// Fall back to iso-8859-1 if invalid/unsupported character set found
characterSet = @"iso-8859-1";
}
var textEncoding = Encoding.GetEncoding(characterSet);
var contentDecoder = GetContentDecoder(contentEncoding);
var encodedText = m.Groups["encodedtext"].Value;
return contentDecoder.Invoke(encodedText, textEncoding);
});
}
/// <summary>
/// Determines if a character set is supported
/// </summary>
/// <param name="characterSet">Character set name</param>
/// <returns>Bool representing whether the character set is supported</returns>
private static bool IsSupportedCharacterSet(string characterSet)
{
return Encoding.GetEncodings()
.Where(e => String.Equals(e.Name, characterSet, StringComparison.InvariantCultureIgnoreCase))
.Any();
}
/// <summary>
/// Gets the content encoding type from the encoding character
/// </summary>
/// <param name="contentEncodingCharacter">Content contentEncodingCharacter character</param>
/// <returns>ContentEncoding type</returns>
private static ContentEncoding GetContentEncodingType(string contentEncodingCharacter)
{
switch (contentEncodingCharacter)
{
case "Q":
case "q":
return ContentEncoding.QEncoding;
case "B":
case "b":
return ContentEncoding.Base64;
default:
return ContentEncoding.Unknown;
}
}
/// <summary>
/// Gets the content decoder delegate for the given content encoding type
/// </summary>
/// <param name="contentEncoding">Content encoding type</param>
/// <returns>Decoding delegate</returns>
private static Func<string, Encoding, string> GetContentDecoder(ContentEncoding contentEncoding)
{
switch (contentEncoding)
{
case ContentEncoding.Base64:
return DecodeBase64;
case ContentEncoding.QEncoding:
return DecodeQEncoding;
default:
// Will never get here, but return a "null" delegate anyway
return (s, e) => String.Empty;
}
}
/// <summary>
/// Gets the content encoder delegate for the given content encoding type
/// </summary>
/// <param name="contentEncoding">Content encoding type</param>
/// <returns>Encoding delegate</returns>
private static Func<string, Encoding, string> GetContentEncoder(ContentEncoding contentEncoding)
{
switch (contentEncoding)
{
case ContentEncoding.Base64:
return EncodeBase64;
case ContentEncoding.QEncoding:
return EncodeQEncoding;
default:
// Will never get here, but return a "null" delegate anyway
return (s, e) => String.Empty;
}
}
/// <summary>
/// Decodes a base64 encoded string
/// </summary>
/// <param name="encodedText">Encoded text</param>
/// <param name="textEncoder">Encoding instance for the code page required</param>
/// <returns>Decoded string</returns>
private static string DecodeBase64(string encodedText, Encoding textEncoder)
{
var encodedBytes = Convert.FromBase64String(encodedText);
return textEncoder.GetString(encodedBytes);
}
/// <summary>
/// Encodes a base64 encoded string
/// </summary>
/// <param name="plainText">Plain text</param>
/// <param name="textEncoder">Encoding instance for the code page required</param>
/// <returns>Encoded string</returns>
private static string EncodeBase64(string plainText, Encoding textEncoder)
{
var plainTextBytes = textEncoder.GetBytes(plainText);
return Convert.ToBase64String(plainTextBytes);
}
/// <summary>
/// Decodes a "Q encoded" string
/// </summary>
/// <param name="encodedText">Encoded text</param>
/// <param name="textEncoder">Encoding instance for the code page required</param>
/// <returns>Decoded string</returns>
private static string DecodeQEncoding(string encodedText, Encoding textEncoder)
{
var decodedText = QEncodingSpaceRegEx.Replace(encodedText, " ");
decodedText = QEncodingHexCodeRegEx.Replace(
decodedText,
m =>
{
var hexString = m.Groups["hexcode"].Value;
int characterValue;
if (!int.TryParse(hexString, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out characterValue))
{
return String.Empty;
}
return textEncoder.GetString(new[] { (byte)characterValue });
});
return decodedText;
}
/// <summary>
/// Encodes a "Q encoded" string
/// </summary>
/// <param name="plainText">Plain text</param>
/// <param name="textEncoder">Encoding instance for the code page required</param>
/// <returns>Encoded string</returns>
private static string EncodeQEncoding(string plainText, Encoding textEncoder)
{
if (textEncoder.GetByteCount(plainText) != plainText.Length)
{
throw new ArgumentException("Q encoding only supports single byte encodings", "textEncoder");
}
var specialBytes = textEncoder.GetBytes(SpecialCharacters);
var sb = new StringBuilder(plainText.Length);
var plainBytes = textEncoder.GetBytes(plainText);
// Replace "high" values
for (int i = 0; i < plainBytes.Length; i++)
{
if (plainBytes[i] <= 127 && !specialBytes.Contains(plainBytes[i]))
{
sb.Append(Convert.ToChar(plainBytes[i]));
}
else
{
sb.Append("=");
sb.Append(Convert.ToString(plainBytes[i], 16).ToUpper());
}
}
return sb.ToString().Replace(" ", "_");
}
/// <summary>
/// Builds the full encoded string representation
/// </summary>
/// <param name="characterSet">Characterset to use</param>
/// <param name="contentEncoding">Content encoding to use</param>
/// <param name="encodedContent">Content, encoded to the above parameters</param>
/// <returns>Valid RFC2047 string</returns>
private static string BuildEncodedString(string characterSet, ContentEncoding contentEncoding, string encodedContent)
{
var encodingCharacter = String.Empty;
switch (contentEncoding)
{
case ContentEncoding.Base64:
encodingCharacter = "B";
break;
case ContentEncoding.QEncoding:
encodingCharacter = "Q";
break;
}
var wrapperLength = string.Format(EncodedStringFormat, characterSet, encodingCharacter, String.Empty).Length;
var chunkLength = MaxLineLength - wrapperLength;
if (encodedContent.Length <= chunkLength)
{
return string.Format(EncodedStringFormat, characterSet, encodingCharacter, encodedContent);
}
var sb = new StringBuilder();
foreach (var chunk in SplitStringByLength(encodedContent, chunkLength))
{
sb.AppendFormat(EncodedStringFormat, characterSet, encodingCharacter, chunk);
sb.Append("\r\n ");
}
return sb.ToString();
}
/// <summary>
/// Splits a string into chunks
/// </summary>
/// <param name="inputString">Input string</param>
/// <param name="chunkSize">Size of each chunk</param>
/// <returns>String collection of chunked strings</returns>
public static IEnumerable<string> SplitStringByLength(this string inputString, int chunkSize)
{
for (int index = 0; index < inputString.Length; index += chunkSize)
{
yield return inputString.Substring(index, Math.Min(chunkSize, inputString.Length - index));
}
}
}
}

View File

@ -1,19 +0,0 @@
using System;
namespace Hcs.ClientApi
{
public class HcsActionLogger : IHcsLogger
{
private Action<string> logger;
public HcsActionLogger(Action<string> logger)
{
this.logger = logger;
}
public void WriteLine(string message)
{
logger(message);
}
}
}

View File

@ -1,96 +0,0 @@
using GostCryptography.Base;
using System;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
namespace Hcs.ClientApi
{
public static class HcsCertificateHelper
{
public static bool IsGostPrivateKey(this X509Certificate2 certificate)
{
try
{
if (certificate.HasPrivateKey)
{
var cspInfo = certificate.GetPrivateKeyInfo();
if (cspInfo.ProviderType == (int)ProviderType.CryptoPro ||
cspInfo.ProviderType == (int)ProviderType.VipNet ||
cspInfo.ProviderType == (int)ProviderType.CryptoPro_2012_512 ||
cspInfo.ProviderType == (int)ProviderType.CryptoPro_2012_1024)
return true;
else
return false;
}
return false;
}
catch
{
return false;
}
}
public static GostXades.CryptoProviderTypeEnum GetProviderType(this X509Certificate2 certificate)
{
return (GostXades.CryptoProviderTypeEnum)GetProviderInfo(certificate).Item1;
}
public static Tuple<int, string> GetProviderInfo(this X509Certificate2 certificate)
{
if (certificate.HasPrivateKey)
{
var cspInfo = certificate.GetPrivateKeyInfo();
return new Tuple<int, string>(cspInfo.ProviderType, cspInfo.ProviderName);
}
else
throw new Exception("Certificate has no private key");
}
public static X509Certificate2 FindCertificate(Func<X509Certificate2, bool> predicate)
{
if (predicate == null) throw new ArgumentException("Null subject predicate");
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
var collection = store.Certificates
.OfType<X509Certificate2>()
.Where(x => x.HasPrivateKey && x.IsGostPrivateKey());
var now = DateTime.Now;
return collection.First(
x => now >= x.NotBefore && now <= x.NotAfter && predicate(x));
}
finally
{
store.Close();
}
}
public static X509Certificate2 ShowCertificateUI()
{
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
var collection = store.Certificates
.OfType<X509Certificate2>()
.Where(x => x.HasPrivateKey && x.IsGostPrivateKey());
string prompt = "Выберите сертификат";
var cert = X509Certificate2UI.SelectFromCollection(
new X509Certificate2Collection(
collection.ToArray()), prompt, "", X509SelectionFlag.SingleSelection)[0];
return cert;
}
finally
{
store.Close();
}
}
}
}

View File

@ -1,74 +0,0 @@
using GostCryptography.Gost_R3411;
using Hcs.ClientApi.DebtRequestsApi;
using Hcs.ClientApi.DeviceMeteringApi;
using Hcs.ClientApi.FileStoreServiceApi;
using Hcs.ClientApi.HouseManagementApi;
using Hcs.ClientApi.NsiApi;
using Hcs.ClientApi.NsiCommonApi;
using Hcs.ClientApi.OrgRegistryCommonApi;
using Hcs.ClientApi.RemoteCaller;
using System;
using System.Security.Cryptography.X509Certificates;
namespace Hcs.ClientApi
{
/// <summary>
/// Единый клиент для вызова всех реализованных функций интеграции с ГИС ЖКХ
/// </summary>
public class HcsClient : HcsClientConfig
{
public HcsClient()
{
HcsServicePointConfig.InitConfig();
// TODO: Вынести в конфиг
// Роль поставщика информации по умолчанию
Role = HcsOrganizationRoles.RSO;
}
public void SetSigningCertificate(X509Certificate2 cert, string pin = null)
{
if (cert == null) throw new ArgumentNullException("Не указан сертификат для подписания данных");
if (pin == null) pin = HcsConstants.DefaultCertificatePin;
Certificate = cert;
CertificateThumbprint = cert.Thumbprint;
CertificatePassword = pin;
CryptoProviderType = cert.GetProviderType();
}
public HcsDebtRequestsApi DebtRequests => new HcsDebtRequestsApi(this);
public HcsHouseManagementApi HouseManagement => new HcsHouseManagementApi(this);
public HcsOrgRegistryCommonApi OrgRegistryCommon => new HcsOrgRegistryCommonApi(this);
public HcsFileStoreServiceApi FileStoreService => new HcsFileStoreServiceApi(this);
public HcsDeviceMeteringApi DeviceMeteringService => new HcsDeviceMeteringApi(this);
public HcsNsiApi Nsi => new HcsNsiApi(this);
public HcsNsiCommonApi NsiCommon => new HcsNsiCommonApi(this);
public X509Certificate2 FindCertificate(Func<X509Certificate2, bool> predicate)
{
return HcsCertificateHelper.FindCertificate(predicate);
}
public X509Certificate2 ShowCertificateUI()
{
return HcsCertificateHelper.ShowCertificateUI();
}
/// <summary>
/// Производит для потока хэш по алгоритму "ГОСТ Р 34.11-94" в строке binhex
/// </summary>
public string ComputeGost94Hash(System.IO.Stream stream)
{
// API HouseManagement указывает, что файлы приложенные к договору должны размещаться
// с AttachmentHASH по стандарту ГОСТ. Оказывается, ГИСЖКХ требует применения устаревшего
// алгоритма ГОСТ Р 34.11-94 (соответствует `rhash --gost94-cryptopro file` в linux).
using var algorithm = new Gost_R3411_94_HashAlgorithm(GostCryptoProviderType);
var savedPosition = stream.Position;
stream.Position = 0;
var hashValue = HcsUtil.ConvertToHexString(algorithm.ComputeHash(stream));
stream.Position = savedPosition;
return hashValue;
}
}
}

View File

@ -1,95 +0,0 @@
using System.Security.Cryptography.X509Certificates;
namespace Hcs.ClientApi
{
/// <summary>
/// Конфигурация клиента
/// </summary>
public class HcsClientConfig
{
/// <summary>
/// Идентификатор поставщика данных ГИС
/// </summary>
public string OrgPPAGUID { get; set; }
/// <summary>
/// Идентификатор организации в ГИС
/// </summary>
public string OrgEntityGUID { get; set; }
/// <summary>
/// Тип криптопровайдера полученный из сертификата
/// </summary>
public GostXades.CryptoProviderTypeEnum CryptoProviderType { get; internal set; }
public GostCryptography.Base.ProviderType GostCryptoProviderType =>
(GostCryptography.Base.ProviderType)CryptoProviderType;
/// <summary>
/// Сертификат клиента для применения при формировании запросов
/// </summary>
public X509Certificate2 Certificate { get; internal set; }
/// <summary>
/// Отпечаток сертификата
/// </summary>
public string CertificateThumbprint { get; internal set; }
/// <summary>
/// Пароль доступа к сертификату
/// </summary>
public string CertificatePassword { get; internal set; }
/// <summary>
/// Исполнитель/сотрудник ГИСЖКХ от которого будут регистрироваться ответы
/// </summary>
public string ExecutorGUID { get; set; }
/// <summary>
/// Признак - указывает на то, что используется внешний туннель (stunnel)
/// </summary>
public bool UseTunnel { get; set; }
/// <summary>
/// true - использовать адреса ППАК стенда иначе СИТ
/// </summary>
public bool IsPPAK { get; set; }
/// <summary>
/// Роль
/// </summary>
public HcsOrganizationRoles Role { get; set; }
/// <summary>
/// Устанавливаемый пользователем приемник отладочных сообщений
/// </summary>
public IHcsLogger Logger { get; set; }
/// <summary>
/// Выводит сообщение в установленный приемник отладочных сообщений
/// </summary>
public void Log(string message) => Logger?.WriteLine(message);
/// <summary>
/// Устанавливаемый пользователем механизм перехвата содержимого отправляемых
/// и принимаемых пакетов
/// </summary>
public IHcsMessageCapture MessageCapture;
/// <summary>
/// Отправляет тело сообщения в установленный перехватчик
/// </summary>
public void MaybeCaptureMessage(bool sent, string messageBody)
=> MessageCapture?.CaptureMessage(sent, messageBody);
public string ComposeEndpointUri(string endpointName)
{
if (UseTunnel)
return $"http://{HcsConstants.Address.UriTunnel}/{endpointName}";
return IsPPAK ?
$"https://{HcsConstants.Address.UriPPAK}/{endpointName}"
: $"https://{HcsConstants.Address.UriSIT02}/{endpointName}";
}
}
}

View File

@ -1,12 +0,0 @@
using System;
namespace Hcs.ClientApi
{
public class HcsConsoleLogger : IHcsLogger
{
public void WriteLine(string message)
{
Console.WriteLine(message);
}
}
}

View File

@ -1,119 +0,0 @@
using System.Collections.Generic;
namespace Hcs.ClientApi
{
public static class HcsConstants
{
/// <summary>
/// Имя XML-элемента в сообщении, которое будет подписываться в фильтре
/// отправки подписывающем XML
/// </summary>
public const string SignedXmlElementId = "signed-data-container";
/// <summary>
/// Если PIN сертификата не указан пользователем, применяется это значение
/// по умолчанию для сертификатов RuToken
/// </summary>
public const string DefaultCertificatePin = "12345678";
public static class Address
{
public const string UriPPAK = "api.dom.gosuslugi.ru";
public const string UriSIT01 = "sit01.dom.test.gosuslugi.ru:10081";
public const string UriSIT02 = "sit02.dom.test.gosuslugi.ru:10081";
public const string UriTunnel = "127.0.0.1:8080";
}
public static class EndPointLocator
{
static Dictionary<HcsEndPoints, string> _endPoints;
static EndPointLocator()
{
if (_endPoints == null)
_endPoints = new Dictionary<HcsEndPoints, string>();
_endPoints.Add(HcsEndPoints.BillsAsync, "ext-bus-bills-service/services/BillsAsync");
_endPoints.Add(HcsEndPoints.DeviceMetering, "ext-bus-device-metering-service/services/DeviceMetering");
_endPoints.Add(HcsEndPoints.DeviceMeteringAsync, "ext-bus-device-metering-service/services/DeviceMeteringAsync");
_endPoints.Add(HcsEndPoints.HomeManagement, "ext-bus-home-management-service/services/HomeManagement");
_endPoints.Add(HcsEndPoints.HomeManagementAsync, "ext-bus-home-management-service/services/HomeManagementAsync");
_endPoints.Add(HcsEndPoints.DebtRequestsAsync, "ext-bus-debtreq-service/services/DebtRequestsAsync");
_endPoints.Add(HcsEndPoints.Licenses, "ext-bus-licenses-service/services/Licenses");
_endPoints.Add(HcsEndPoints.LicensesAsync, "ext-bus-licenses-service/services/LicensesAsync");
_endPoints.Add(HcsEndPoints.Nsi, "ext-bus-nsi-service/services/Nsi");
_endPoints.Add(HcsEndPoints.NsiAsync, "ext-bus-nsi-service/services/NsiAsync");
_endPoints.Add(HcsEndPoints.NsiCommon, "ext-bus-nsi-common-service/services/NsiCommon");
_endPoints.Add(HcsEndPoints.NsiCommonAsync, "ext-bus-nsi-common-service/services/NsiCommonAsync");
_endPoints.Add(HcsEndPoints.OrgRegistryCommon, "ext-bus-org-registry-common-service/services/OrgRegistryCommon");
_endPoints.Add(HcsEndPoints.OrgRegistryCommonAsync, "ext-bus-org-registry-common-service/services/OrgRegistryCommonAsync");
_endPoints.Add(HcsEndPoints.OrgRegistry, "ext-bus-org-registry-service/services/OrgRegistry");
_endPoints.Add(HcsEndPoints.OrgRegistryAsync, "ext-bus-org-registry-service/services/OrgRegistryAsync");
_endPoints.Add(HcsEndPoints.PaymentsAsync, "ext-bus-payment-service/services/PaymentAsync");
}
public static string GetPath(HcsEndPoints endPoint)
{
return _endPoints[endPoint];
}
}
public static class UserAuth
{
public const string Name = "sit";
public const string Passwd = "xw{p&&Ee3b9r8?amJv*]";
}
}
/// <summary>
/// Имена конечных точек
/// </summary>
public enum HcsEndPoints
{
OrgRegistry,
OrgRegistryAsync,
OrgRegistryCommon,
OrgRegistryCommonAsync,
NsiCommon,
NsiCommonAsync,
Nsi,
NsiAsync,
HomeManagement,
HomeManagementAsync,
DebtRequestsAsync,
Bills,
BillsAsync,
Licenses,
LicensesAsync,
DeviceMetering,
DeviceMeteringAsync,
PaymentsAsync
}
/// <summary>
/// Роли организаций в ГИС
/// </summary>
public enum HcsOrganizationRoles
{
/// <summary>
/// УК/ТСЖ/ЖСК
/// </summary>
UK,
/// <summary>
/// Ресурсоснабжающая организация
/// </summary>
RSO,
/// <summary>
/// Расчетный центр
/// </summary>
RC,
}
public class HcsAsyncRequestStateTypes
{
public const int Received = 1;
public const int InProgress = 2;
public const int Ready = 3;
}
}

View File

@ -1,29 +0,0 @@
using System;
using System.Linq;
namespace Hcs.ClientApi
{
public class HcsException : Exception
{
public HcsMemoryMessageCapture MessageCapture { get; private set; }
public HcsException(string message) : base(message)
{
}
public HcsException(string message, Exception nestedException) : base(message, nestedException)
{
}
public HcsException(string message, HcsMemoryMessageCapture capture, Exception nestedException)
: base(message, nestedException)
{
MessageCapture = capture;
}
public static HcsException FindHcsException(Exception e)
{
return HcsUtil.EnumerateInnerExceptions(e).OfType<HcsException>().FirstOrDefault();
}
}
}

View File

@ -1,55 +0,0 @@
using System;
using System.IO;
using System.Linq;
namespace Hcs.ClientApi
{
public class HcsFile
{
public string FileName { get; private set; }
public string ContentType { get; private set; }
public Stream Stream { get; private set; }
public long Length => Stream.Length;
public HcsFile(string fileName, string contentType, Stream stream)
{
FileName = fileName;
ContentType = contentType ?? throw new ArgumentNullException(nameof(ContentType));
Stream = stream ?? throw new ArgumentNullException(nameof(stream));
}
/// <summary>
/// По имени файла возвращает строку MIME Content-Type или null если тип MIME не найден
/// </summary>
public static string GetMimeContentTypeForFileName(string fileName)
{
if (string.IsNullOrEmpty(fileName)) return null;
string extension = Path.GetExtension(fileName).ToLower();
var mimeType = AllowedMimeTypes.FirstOrDefault(x => x.Extension == extension);
if (mimeType == null) return null;
return mimeType.ContentType;
}
public record struct MimeType(string Extension, string ContentType);
/// <summary>
/// Типы MIME допустимые для загрузки в ГИС ЖКХ
/// </summary>
public static MimeType[] AllowedMimeTypes =
{
new MimeType(".pdf", "application/pdf"),
new MimeType(".xls", "application/excel"),
new MimeType(".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
new MimeType(".doc", "application/msword"),
new MimeType(".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
new MimeType(".rtf", "application/rtf"),
new MimeType(".jpg", "image/jpeg"),
new MimeType(".jpeg", "image/jpeg"),
new MimeType(".tif", "image/tiff"),
new MimeType(".tiff", "image/tiff")
// TODO: Проверить комментарий
// В спецификации есть другие типы файлов .zip, .sgn и т.д.
};
}
}

View File

@ -1,37 +0,0 @@
namespace Hcs.ClientApi
{
/// <summary>
/// Раздел хранилища файлов (Attachment) из документации: "ГИС ЖКХ. Альбом ТФФ 14.5.0.1.docx"
/// 2.6 Перечень контекстов хранилищ функциональных подсистем
/// </summary>
public enum HcsFileStoreContext
{
/// <summary>
/// Управление домами. Лицевые счета.
/// </summary>
homemanagement,
/// <summary>
/// Управление контентом
/// </summary>
contentmanagement,
/// <summary>
/// Электронные счета
/// </summary>
bills,
/// <summary>
/// Запросов о наличии задолженности по оплате ЖКУ
/// </summary>
debtreq
}
public static class HcsFileStoreContextExtensions
{
public static string GetName(this HcsFileStoreContext context)
{
return context.ToString();
}
}
}

View File

@ -1,45 +0,0 @@
using System.Text;
namespace Hcs.ClientApi
{
/// <summary>
/// Реализация механизма захвата содержимого сообщений SOAP записывающая
/// каждое сообщение в отдельный файл на диске
/// </summary>
public class HcsFileWriterMessageCapture : IHcsMessageCapture
{
private string directory;
private IHcsLogger logger;
public HcsFileWriterMessageCapture()
{
}
public HcsFileWriterMessageCapture(string directory, IHcsLogger logger)
{
this.directory = directory;
this.logger = logger;
}
public void CaptureMessage(bool sent, string body)
{
int index = 0;
int maxIndex = 1000000;
string fileName;
do
{
index += 1;
if (index > maxIndex) throw new HcsException("Превышен максимум индекса файлов захвата сообщений");
fileName = index.ToString("D3") + "_" + (sent ? "message" : "response") + ".xml";
if (!string.IsNullOrEmpty(directory))
{
fileName = System.IO.Path.Combine(directory, fileName);
}
} while (System.IO.File.Exists(fileName));
if (logger != null) logger.WriteLine($"Writing message file: {fileName}...");
System.IO.File.WriteAllText(fileName, body, Encoding.UTF8);
}
}
}

View File

@ -1,49 +0,0 @@
using System;
using System.IO;
using System.Text;
namespace Hcs.ClientApi
{
/// <summary>
/// Реализация захвата содержимого отправляемых и принимаемых SOAP сообщений,
/// которая хранит данные в памяти
/// </summary>
public class HcsMemoryMessageCapture : IHcsMessageCapture
{
private MemoryStream messageCaptureStream;
private StreamWriter messageCaptureWriter;
private Encoding encoding => Encoding.UTF8;
public HcsMemoryMessageCapture()
{
messageCaptureStream = new MemoryStream();
messageCaptureWriter = new StreamWriter(messageCaptureStream, encoding);
}
void IHcsMessageCapture.CaptureMessage(bool sentOrReceived, string messageBody)
{
if (messageCaptureStream.Position > 0) messageCaptureWriter.WriteLine("");
messageCaptureWriter.Write("<!--");
messageCaptureWriter.Write(sentOrReceived ? "SENT " : "RECV ");
messageCaptureWriter.Write(DateTime.Now.ToString());
messageCaptureWriter.WriteLine("-->");
messageCaptureWriter.Write(messageBody);
messageCaptureWriter.Flush();
}
public byte[] GetData()
{
var buf = messageCaptureStream.GetBuffer();
int size = (int)messageCaptureStream.Length;
var data = new byte[size];
Buffer.BlockCopy(buf, 0, data, 0, size);
return data;
}
public override string ToString()
{
return encoding.GetString(GetData());
}
}
}

View File

@ -1,26 +0,0 @@
using System;
namespace Hcs.ClientApi
{
/// <summary>
/// Исключение указывает на то что сервер обнаружил что у
/// него нет объектов для выдачи по условию
/// </summary>
public class HcsNoResultsRemoteException : HcsRemoteException
{
public HcsNoResultsRemoteException(string description) :
base(HcsRemoteException.KnownCodes.НетОбъектовДляЭкспорта, description)
{
}
public HcsNoResultsRemoteException(string errorCode, string description) :
base(errorCode, description)
{
}
public HcsNoResultsRemoteException(string errorCode, string description, Exception nested) :
base(errorCode, description, nested)
{
}
}
}

View File

@ -1,76 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Hcs.ClientApi
{
public class HcsParallel
{
/// <summary>
/// Асинхронно обрабатывает все элементы @values типа @T методом @processor в параллельном режиме,
/// используя максимум @maxThreads потоков
/// </summary>
public static async Task ForEachAsync<T>(IEnumerable<T> values, Func<T, Task> processor, int maxThreads)
{
await Task.Run(() => ForEach(values, processor, maxThreads));
}
/// <summary>
/// Обрабатывает все элементы @values типа @T методом @processor в параллельном режиме,
/// используя максимум @maxThreads потоков
/// </summary>
public static void ForEach<T>(IEnumerable<T> values, Func<T, Task> processor, int maxThreads)
{
var taskList = new List<Task>();
var enumerator = values.GetEnumerator();
int numTasksFinished = 0;
while (true)
{
// Наполняем массив ожидания следующими задачами
while (taskList.Count < maxThreads)
{
if (!enumerator.MoveNext()) break;
// Запускаем новую задачу в отсоединенном потоке
Task newTask = Task.Run(() => processor(enumerator.Current));
taskList.Add(newTask);
}
// Если массив ожидания пуст, работа окончена
if (taskList.Count == 0) return;
// Ждем завершение любой задачи из массива ожидания
int finishedIndex = Task.WaitAny(taskList.ToArray());
var finishedTask = taskList[finishedIndex];
numTasksFinished += 1;
// Удаляем задачу из массива ожидания чтобы более ее не ждать
taskList.Remove(finishedTask);
// Если задача завершилась успешно уходим на добавление новой задачи
if (!finishedTask.IsFaulted &&
!finishedTask.IsCanceled) continue;
// Задача завершилась аномально, ждем завершения других запущенных задач
if (taskList.Count > 0) Task.WaitAll(taskList.ToArray());
// Составляем список всех возникших ошибок включая первую
taskList.Insert(0, finishedTask);
var errors = new List<Exception>();
foreach (var task in taskList)
{
if (task.IsFaulted) errors.Add(task.Exception);
if (task.IsCanceled) errors.Add(new Exception("Task was cancelled"));
}
// Аномально завершаем обработку
string message =
$"Ошибка параллельной обработки №{numTasksFinished} из {values.Count()}" +
$" объектов типа {typeof(T).FullName}";
throw new AggregateException(message, errors.ToArray());
}
}
}
}

View File

@ -1,80 +0,0 @@
using System;
using System.IO;
namespace Hcs.ClientApi
{
/// <summary>
/// Поток байтов который является частью другого потока байтов
/// https://stackoverflow.com/questions/60592147/partial-stream-of-filestream
/// </summary>
public class HcsPartialStream : Stream
{
public Stream Stream { get; private set; }
public long StreamStart { get; private set; }
public long StreamLength { get; private set; }
public long StreamEnd { get; private set; }
public HcsPartialStream(Stream stream, long offset, long size)
{
Stream = stream;
StreamStart = offset;
StreamLength = size;
StreamEnd = offset + size;
stream.Seek(offset, SeekOrigin.Begin);
}
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override long Length => Math.Min((Stream.Length - StreamStart), StreamLength);
public override long Position
{
get => Stream.Position - StreamStart;
set => Stream.Position = StreamStart + value;
}
public override void Flush()
{
throw new NotImplementedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
var p = Stream.Position;
if (p < StreamStart)
{
Stream.Position = StreamStart;
}
if (p > StreamEnd)
{
return 0;
}
if (p + count > StreamEnd)
{
count = (int)(StreamEnd - p);
}
return Stream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
// Seek will be complicated as there are three origin types.
// You can do it yourself.
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
}
}

View File

@ -1,60 +0,0 @@
using System;
using System.Linq;
namespace Hcs.ClientApi
{
/// <summary>
/// Сообщение об ошибке возникшей на удаленном сервере ГИС ЖКХ
/// </summary>
public class HcsRemoteException : HcsException
{
public string ErrorCode { get; private set; }
public string Description { get; private set; }
public class KnownCodes
{
public const string НетОбъектовДляЭкспорта = "INT002012";
public const string ОтсутствуетВРеестре = "INT002000";
public const string ДоступЗапрещен = "AUT011003";
}
public HcsRemoteException(string errorCode, string description)
: base(MakeMessage(errorCode, description))
{
this.ErrorCode = errorCode;
this.Description = description;
}
public HcsRemoteException(string errorCode, string description, Exception nestedException)
: base(MakeMessage(errorCode, description), nestedException)
{
this.ErrorCode = errorCode;
this.Description = description;
}
private static string MakeMessage(string errorCode, string description)
=> $"Удаленная система вернула ошибку: [{errorCode}] {description}";
public static HcsRemoteException CreateNew(string errorCode, string description, Exception nested = null)
{
if (string.Compare(errorCode, KnownCodes.НетОбъектовДляЭкспорта) == 0)
return new HcsNoResultsRemoteException(errorCode, description, nested);
return new HcsRemoteException(errorCode, description);
}
public static HcsRemoteException CreateNew(HcsRemoteException nested)
{
if (nested == null) throw new ArgumentNullException("nested exception");
return CreateNew(nested.ErrorCode, nested.Description, nested);
}
/// <summary>
/// Возвращает true если ошибка @e или ее вложенные ошибки модержат @errorCode
/// </summary>
public static bool ContainsErrorCode(Exception e, string errorCode)
{
if (e == null) return false;
return HcsUtil.EnumerateInnerExceptions(e).OfType<HcsRemoteException>().Where(x => x.ErrorCode == errorCode).Any();
}
}
}

View File

@ -1,15 +0,0 @@
using System;
namespace Hcs.ClientApi
{
public class HcsRestartTimeoutException : HcsException
{
public HcsRestartTimeoutException(string message) : base(message)
{
}
public HcsRestartTimeoutException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -1,91 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Hcs.ClientApi
{
public class HcsUtil
{
/// <summary>
/// Возвращает описание исключения одной строкой
/// </summary>
public static string DescribeException(Exception e)
{
string separator = "";
var buf = new StringBuilder();
buf.Append("[");
foreach (var inner in EnumerateInnerExceptions(e))
{
buf.Append(separator);
buf.Append(inner.GetType().Name);
buf.Append(":");
buf.Append(inner.Message);
separator = "-->";
}
buf.Append("]");
return buf.ToString();
}
/// <summary>
/// Возвращает список все вложенных исключений для данного исключения
/// </summary>
public static List<Exception> EnumerateInnerExceptions(Exception e)
{
var list = new List<Exception>();
WalkInnerExceptionsRecurse(e, list);
return list;
}
private static void WalkInnerExceptionsRecurse(Exception e, List<Exception> list)
{
if (e == null || list.Contains(e)) return;
list.Add(e);
WalkInnerExceptionsRecurse(e.InnerException, list);
if (e is AggregateException)
{
var aggregate = e as AggregateException;
foreach (var inner in aggregate.InnerExceptions)
{
WalkInnerExceptionsRecurse(inner, list);
}
}
}
public static string FormatGuid(Guid guid) => guid.ToString();
public static Guid ParseGuid(string guid)
{
try
{
return Guid.Parse(guid);
}
catch (Exception e)
{
throw new HcsException($"Невозможно прочитать GUID из строки [{guid}]", e);
}
}
public static string FormatDate(DateTime date)
{
return date.ToString("yyyyMMdd");
}
public static string FormatDate(DateTime? date)
{
return (date == null) ? string.Empty : FormatDate((DateTime)date);
}
/// <summary>
/// Преобразует массиб байтов в строку в формате binhex
/// </summary>
public static string ConvertToHexString(byte[] ba)
{
var buf = new StringBuilder(ba.Length * 2);
foreach (byte b in ba) buf.AppendFormat("{0:x2}", b);
return buf.ToString();
}
}
}

View File

@ -1,229 +0,0 @@
using Org.BouncyCastle.Asn1;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace Hcs.ClientApi
{
/// <summary>
/// Методы работы с сертификатами X509, которых нет в системе
/// </summary>
public class HcsX509Tools
{
public static bool IsValidCertificate(X509Certificate2 cert)
{
var now = DateTime.Now;
return (now >= cert.NotBefore && now <= GetNotAfterDate(cert));
}
public static IEnumerable<X509Certificate2> EnumerateCertificates(bool includeInvalid = false)
{
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
try
{
var now = DateTime.Now;
foreach (var x in store.Certificates)
{
if (includeInvalid) yield return x;
else if (IsValidCertificate(x)) yield return x;
}
}
finally
{
store.Close();
}
}
public static X509Certificate2 FindCertificate(Func<X509Certificate2, bool> predicate)
{
if (predicate == null) throw new ArgumentException("Null subject predicate");
return EnumerateCertificates(true).FirstOrDefault(x => predicate(x));
}
public static X509Certificate2 FindValidCertificate(Func<X509Certificate2, bool> predicate)
{
if (predicate == null) throw new ArgumentException("Null subject predicate");
return EnumerateCertificates(false).FirstOrDefault(x => predicate(x));
}
/// <summary>
/// Возвращает Common Name сертификата
/// </summary>
public static string GetCommonName(X509Certificate2 x509cert)
{
return x509cert.GetNameInfo(X509NameType.SimpleName, false);
}
/// <summary>
/// Возвращает дату окончания действия сертификата
/// </summary>
public static DateTime GetNotAfterDate(X509Certificate2 x509cert)
{
// Сначала пытаемся определить срок первичного ключа, а затем уже самого сертификата
DateTime? датаОкончания = GetPrivateKeyUsageEndDate(x509cert);
if (датаОкончания != null) return (DateTime)датаОкончания;
return x509cert.NotAfter;
}
/// <summary>
/// Известные номера расширений сертификата
/// </summary>
private class KnownOids
{
public const string PrivateKeyUsagePeriod = "2.5.29.16";
}
public static DateTime? GetPrivateKeyUsageEndDate(X509Certificate2 x509cert)
{
foreach (var ext in x509cert.Extensions)
{
if (ext.Oid.Value == KnownOids.PrivateKeyUsagePeriod)
{
// Дата начала с индексом 0, дата окончания с индексом 1
return ParseAsn1Datetime(ext, 1);
}
}
return null;
}
/// <summary>
/// Разбирает значение типа дата из серии значений ASN1 присоединенных к расширению
/// </summary>
private static DateTime? ParseAsn1Datetime(X509Extension ext, int valueIndex)
{
try
{
Asn1Object asnObject = (new Asn1InputStream(ext.RawData)).ReadObject();
if (asnObject == null) return null;
var asnSequence = Asn1Sequence.GetInstance(asnObject);
if (asnSequence.Count <= valueIndex) return null;
var asn = (Asn1TaggedObject)asnSequence[valueIndex];
var asnStr = Asn1OctetString.GetInstance(asn, false);
string s = Encoding.UTF8.GetString(asnStr.GetOctets());
int year = int.Parse(s.Substring(0, 4));
int month = int.Parse(s.Substring(4, 2));
int day = int.Parse(s.Substring(6, 2));
int hour = int.Parse(s.Substring(8, 2));
int minute = int.Parse(s.Substring(10, 2));
int second = int.Parse(s.Substring(12, 2));
// Последний символ - буква 'Z'
return new DateTime(year, month, day, hour, minute, second);
}
catch (Exception)
{
return null;
}
}
public static string ДатьСтрокуФИОСертификатаСДатойОкончания(X509Certificate2 x509cert)
{
var фио = ДатьФИОСертификата(x509cert);
return фио.Фамилия + " " + фио.Имя + " " + фио.Отчество +
" до " + GetNotAfterDate(x509cert).ToString("dd.MM.yyyy");
}
public static string ДатьСтрокуФИОСертификата(X509Certificate2 x509cert)
{
var фио = ДатьФИОСертификата(x509cert);
return фио.Фамилия + " " + фио.Имя + " " + фио.Отчество;
}
/// <summary>
/// Возвращает массив из трех строк, содержащих соответственно Фамилию, Имя и Отчество
/// полученных из данных сертификата. Если сертификат не содержит ФИО возвращается массив
/// из трех пустых строк. Это не точный метод определять имя, он предполагает что
/// поля SN, G, CN содержат ФИО в определенном порядке, что правдоподобно но не обязательно.
/// </summary>
public static (string Фамилия, string Имя, string Отчество) ДатьФИОСертификата(X509Certificate2 x509cert)
{
string фам = "", имя = "", отч = "";
// Сначала ищем поля surname (SN) и given-name (G)
string sn = DecodeSubjectField(x509cert, "SN");
string g = DecodeSubjectField(x509cert, "G");
if (!string.IsNullOrEmpty(sn) && !string.IsNullOrEmpty(g))
{
фам = sn;
string[] gParts = g.Split(' ');
if (gParts != null && gParts.Length >= 1) имя = gParts[0];
if (gParts != null && gParts.Length >= 2) отч = gParts[1];
}
else
{
// Иначе берем три первых слова из common name (CN), игнорируя кавычки
string cn = DecodeSubjectField(x509cert, "CN");
if (!string.IsNullOrEmpty(cn))
{
cn = new StringBuilder(cn).Replace("\"", "").ToString();
char[] separators = { ' ', ';' };
string[] cnParts = cn.Split(separators);
if (cnParts != null && cnParts.Length >= 1) фам = cnParts[0];
if (cnParts != null && cnParts.Length >= 2) имя = cnParts[1];
if (cnParts != null && cnParts.Length >= 3) отч = cnParts[2];
}
}
return (фам, имя, отч);
}
/// <summary>
/// Возвращает строку ИНН владельца сертификата
/// </summary>
public static string ДатьИННСертификата(X509Certificate2 x509cert)
{
return DecodeSubjectField(x509cert, "ИНН");
}
/// <summary>
/// Возвращает значение поля с именем @subName включенного в различимое имя Subject
/// </summary>
private static string DecodeSubjectField(X509Certificate2 x509cert, string subName)
{
// Чтобы посмотреть все поля сертификата
//System.Diagnostics.Trace.WriteLine("x509decode=" + x509cert.SubjectName.Decode(
//X500DistinguishedNameFlags.UseNewLines));
// Декодируем различимое имя на отдельные строки через переводы строк для надежности разбора
string decoded = x509cert.SubjectName.Decode(X500DistinguishedNameFlags.UseNewLines);
char[] separators = { '\n', '\r' };
string[] parts = decoded.Split(separators, StringSplitOptions.RemoveEmptyEntries);
if (parts == null) return null;
// Каждая часть начинается с имени и отделяется от значения символом равно
foreach (string part in parts)
{
if (part.Length <= subName.Length + 1) continue;
if (part.StartsWith(subName) && part[subName.Length] == '=')
{
return part.Substring(subName.Length + 1);
}
}
return null;
}
public static int Compare(X509Certificate2 x, X509Certificate2 y)
{
if (x == null && y != null) return -1;
if (x != null && y == null) return 1;
if (x == null && y == null) return 0;
// Сначала сравниваем ФИО
int sign = string.Compare(ДатьСтрокуФИОСертификата(x), ДатьСтрокуФИОСертификата(y), true);
if (sign != 0) return sign;
// Затем дату окончания действия
return GetNotAfterDate(x).CompareTo(GetNotAfterDate(y));
}
public class CertificateComparer : IComparer<X509Certificate2>
{
public int Compare(X509Certificate2 x, X509Certificate2 y) => HcsX509Tools.Compare(x, y);
}
}
}

View File

@ -1,132 +0,0 @@
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 все;
}
}
}

View File

@ -1,189 +0,0 @@
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);
}
}
}

View File

@ -1,162 +0,0 @@
using Hcs.ClientApi.RemoteCaller;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using HouseManagement = Hcs.Service.Async.HouseManagement.v15_7_0_1;
namespace Hcs.Service.Async.HouseManagement.v15_7_0_1
{
public partial class AckRequestAck : IHcsAck { }
public partial class getStateResult : IHcsGetStateResultMany { }
public partial class Fault : IHcsFault { }
public partial class HeaderType : IHcsHeaderType { }
}
namespace Hcs.ClientApi.HouseManagementApi
{
public class HcsHouseManagementMethod : HcsRemoteCallMethod<IHcsGetStateResultMany>
{
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<IHcsGetStateResultMany> 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<IHcsGetStateResultMany> 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<IHcsGetStateResultMany> 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(IHcsGetStateResultMany stateResult)
{
return ParseImportResults(stateResult, 1, true).First();
}
/// <summary>
/// Разбирает стандартный ответ HCS на операцию импорта с приемом ошибок
/// </summary>
protected HouseManagement.getStateResultImportResultCommonResult[] ParseImportResults(
IHcsGetStateResultMany 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); });
}
}
}

View File

@ -1,126 +0,0 @@
using HouseManagement = Hcs.Service.Async.HouseManagement.v15_7_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 = "Электроснабжение"
};
// TODO: Подставить корректный код и ГУИД
public static HouseManagement.ContractSubjectTypeMunicipalResource ElectricSupplyMunicipalResource
=> new HouseManagement.ContractSubjectTypeMunicipalResource()
{
Code = "8",
GUID = "7379be86-6c95-4e41-b000-3bc703d35969",
Name = "Электрическая энергия"
};
public static HouseManagement.ContractSubjectTypeServiceType HeatingSupplyServiceType
=> new HouseManagement.ContractSubjectTypeServiceType()
{
Code = "6",
GUID = "74925764-ddf3-4b4b-b18d-85994187c13a",
Name = "Отопление"
};
public static HouseManagement.ContractSubjectTypeMunicipalResource HeatingSupplyMunicipalResource
=> new HouseManagement.ContractSubjectTypeMunicipalResource()
{
// Значения взяты из справочника 239
Code = "4",
GUID = "eec6e4b8-76c8-4fce-99b7-c95718edad19",
Name = null
};
public static HouseManagement.ContractSubjectTypeServiceType HotWaterSupplyServiceType
=> new HouseManagement.ContractSubjectTypeServiceType()
{
Code = "2",
GUID = "ee8c6a41-aaf8-41c8-a1f6-5832cc622f88",
Name = null
};
// TODO: Подставить корректный код и ГУИД
public static HouseManagement.ContractSubjectTypeMunicipalResource HotWaterSupplyMunicipalResource
=> new HouseManagement.ContractSubjectTypeMunicipalResource()
{
Code = "2.2",
GUID = "1471de55-c2e7-4101-9f2a-9bef6fffb896",
Name = "Горячая вода 2"
};
}
}

View File

@ -1,190 +0,0 @@
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.v15_7_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.ItemsChoiceType26> { };
List<string> items = new List<string> { };
if (fiasHouseGuid != null)
{
itemNames.Add(HouseManagement.ItemsChoiceType26.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.ItemsChoiceType26.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.ItemsChoiceType17.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.ItemsChoiceType18.ContractGUID:
основание.ГуидДоговора = ParseGuid(itemValue);
break;
case HouseManagement.ItemsChoiceType18.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.ItemChoiceType11.FIASHouseGuid: размещение.ГуидЗдания = ParseGuid(source.Item); break;
case HouseManagement.ItemChoiceType11.PremisesGUID: размещение.ГуидПомещения = ParseGuid(source.Item); break;
case HouseManagement.ItemChoiceType11.LivingRoomGUID: размещение.ГуидЖилойКомнаты = ParseGuid(source.Item); break;
default: throw new HcsException("Неизвестный тип размещения ЛС: " + source.ItemElementName);
}
return размещение;
}
}
}

View File

@ -1,101 +0,0 @@
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.v15_7_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)
};
}
}
}

View File

@ -1,165 +0,0 @@
using Hcs.ClientApi.DataTypes;
using Hcs.Service.Async.HouseManagement.v15_7_0_1;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using HouseManagement = Hcs.Service.Async.HouseManagement.v15_7_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.ItemsChoiceType24> itemNames = [HouseManagement.ItemsChoiceType24.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 прибор;
}
}
}

View File

@ -1,297 +0,0 @@
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.v15_7_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.ItemsChoiceType32> { };
List<object> items = new List<object> { };
if (contractRootGuid != null)
{
itemNames.Add(HouseManagement.ItemsChoiceType32.ContractRootGUID);
items.Add(FormatGuid(contractRootGuid));
}
if (contractNumber != null)
{
itemNames.Add(HouseManagement.ItemsChoiceType32.ContractNumber);
items.Add(contractNumber);
}
if (exportNextGuid != null)
{
itemNames.Add(HouseManagement.ItemsChoiceType32.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);
}
}
}
}

View File

@ -1,125 +0,0 @@
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.v15_7_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.ItemsChoiceType34> { };
List<string> items = new List<string> { };
if (договор.ГуидВерсииДоговора != default)
{
itemNames.Add(HouseManagement.ItemsChoiceType34.ContractGUID);
items.Add(FormatGuid(договор.ГуидВерсииДоговора));
}
else
{
itemNames.Add(HouseManagement.ItemsChoiceType34.ContractRootGUID);
items.Add(FormatGuid(договор.ГуидДоговора));
}
// TODO: Проверить комментарий
// Если указан guid следующей страницы данных, добавляем его в параметры
// (на 20.12.2023 эта функция не работает, первый пакет содержит 1000 записей
// и запрос второго пакета с ExportObjectGUID возвращает "Bad request")
if (firstGuid != null)
{
itemNames.Add(HouseManagement.ItemsChoiceType34.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
};
}
}
}

View File

@ -1,192 +0,0 @@
using Hcs.ClientApi.DataTypes;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using HouseManagement = Hcs.Service.Async.HouseManagement.v15_7_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.ItemsChoiceType17.ContractGUID]
};
account.AccountReasons = new HouseManagement.AccountReasonsImportType()
{
SupplyResourceContract = [reasonRSO]
};
account.ItemElementName = HouseManagement.ItemChoiceType8.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.ItemChoiceType9.FIASHouseGuid;
accomodation.Item = FormatGuid(размещение.ГуидЗдания);
}
else if (размещение.ГуидПомещения != null)
{
accomodation.ItemElementName = HouseManagement.ItemChoiceType9.PremisesGUID;
accomodation.Item = FormatGuid(размещение.ГуидПомещения);
}
else if (размещение.ГуидЖилойКомнаты != null)
{
accomodation.ItemElementName = HouseManagement.ItemChoiceType9.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.ItemChoiceType26.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}");
}
}
}
}

View File

@ -1,207 +0,0 @@
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.v15_7_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.ItemChoiceType26.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}");
}
}
}
}

View File

@ -1,392 +0,0 @@
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.v15_7_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.ItemChoiceType32.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.ItemChoiceType26.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.HeatingSupplyServiceType,
MunicipalResource = HcsHouseManagementNsi.HeatingSupplyMunicipalResource,
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.ItemsChoiceType9.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; // Не указана дата окончания поставки ресурса
// TODO: Необходимо указывать только для отопления и ГВС, нужен рефактор кода
pair.HeatingSystemType = new HouseManagement.SupplyResourceContractTypeObjectAddressPairHeatingSystemType()
{
OpenOrNot = HouseManagement.SupplyResourceContractTypeObjectAddressPairHeatingSystemTypeOpenOrNot.Closed,
CentralizedOrNot = HouseManagement.SupplyResourceContractTypeObjectAddressPairHeatingSystemTypeCentralizedOrNot.Centralized
};
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);
}
}
}

View File

@ -1,135 +0,0 @@
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.v15_7_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.ItemChoiceType34.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();
// TODO: Эти значения должны быть регулируемыми
var serviceType = new HouseManagement.ContractSubjectObjectAdressTypeServiceType()
{
Code = HcsHouseManagementNsi.HeatingSupplyServiceType.Code,
GUID = HcsHouseManagementNsi.HeatingSupplyServiceType.GUID,
Name = HcsHouseManagementNsi.HeatingSupplyServiceType.Name
};
// TODO: Эти значения должны быть регулируемыми
var municipalResource = new HouseManagement.ContractSubjectObjectAdressTypeMunicipalResource()
{
Code = HcsHouseManagementNsi.HeatingSupplyMunicipalResource.Code,
GUID = HcsHouseManagementNsi.HeatingSupplyMunicipalResource.GUID,
Name = HcsHouseManagementNsi.HeatingSupplyMunicipalResource.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;
}
}
}

View File

@ -1,80 +0,0 @@
using Hcs.ClientApi.DataTypes;
using Hcs.Service.Async.HouseManagement.v15_7_0_1;
using System;
using System.Threading;
using System.Threading.Tasks;
using HouseManagement = Hcs.Service.Async.HouseManagement.v15_7_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 = ItemChoiceType35.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);
}
}
}

View File

@ -1,10 +0,0 @@
namespace Hcs.ClientApi
{
/// <summary>
/// Интерфейс для механизма вывода отладочных сообщений для обработки вызывающей системой
/// </summary>
public interface IHcsLogger
{
void WriteLine(string message);
}
}

View File

@ -1,11 +0,0 @@
namespace Hcs.ClientApi
{
/// <summary>
/// Интерфейс для механизма захвата отправляемых и принимаемых
/// SOAP сообщений в ходе коммуникации с ГИС ЖКХ
/// </summary>
public interface IHcsMessageCapture
{
void CaptureMessage(bool sentOrReceived, string messageBody);
}
}

View File

@ -1,115 +0,0 @@
using Hcs.ClientApi.DataTypes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Nsi = Hcs.Service.Async.Nsi.v15_7_0_1;
namespace Hcs.ClientApi.NsiApi
{
/// <summary>
/// Операции экспорта данных справочников поставщика информации ГИС ЖКХ
/// </summary>
internal class HcsMethodExportNsi : HcsNsiMethod
{
public HcsMethodExportNsi(HcsClientConfig config) : base(config)
{
EnableMinimalResponseWaitDelay = true;
CanBeRestarted = true;
}
/// <summary>
/// Возвращает данные справочников поставщика информации
/// </summary>
/// <param name="regNum">Реестровый номер справочника</param>
/// <param name="token">Токен отмены</param>
/// <returns>Список справочников</returns>
public async Task<IEnumerable<ГисСправочник>> GetNsiItem(int regNum, CancellationToken token)
{
var request = new Nsi.exportDataProviderNsiItemRequest
{
Id = HcsConstants.SignedXmlElementId,
RegistryNumber = GetRegNumFromInt(regNum),
// http://open-gkh.ru/Nsi/exportDataProviderNsiItemRequest.html
version = "10.0.1.2"
};
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
{
var response = await portClient.exportDataProviderNsiItemAsync(CreateRequestHeader(), request);
return response.AckRequest.Ack;
}, token);
return stateResult.Items
.OfType<Nsi.NsiItemType>()
.Select(x => AdoptNsiItemType(x));
}
private Nsi.exportDataProviderNsiItemRequestRegistryNumber GetRegNumFromInt(int regNum)
{
switch (regNum)
{
case 1:
return Nsi.exportDataProviderNsiItemRequestRegistryNumber.Item1;
case 51:
return Nsi.exportDataProviderNsiItemRequestRegistryNumber.Item51;
case 59:
return Nsi.exportDataProviderNsiItemRequestRegistryNumber.Item59;
case 219:
return Nsi.exportDataProviderNsiItemRequestRegistryNumber.Item219;
case 272:
return Nsi.exportDataProviderNsiItemRequestRegistryNumber.Item272;
case 302:
return Nsi.exportDataProviderNsiItemRequestRegistryNumber.Item302;
case 337:
return Nsi.exportDataProviderNsiItemRequestRegistryNumber.Item337;
default:
throw new NotImplementedException($"Cannot convert {regNum} to {typeof(Nsi.exportDataProviderNsiItemRequestRegistryNumber)}");
}
}
private ГисСправочник AdoptNsiItemType(Nsi.NsiItemType input)
{
var справочник = new ГисСправочник()
{
реестровыйНомер = input.NsiItemRegistryNumber,
датаФормирования = input.Created,
элементы = AdoptNsiElementTypes(input.NsiElement)
};
return справочник;
}
private ГисЭлементСправочника[] AdoptNsiElementTypes(Nsi.NsiElementType[] input)
{
var элементыСправочника = new List<ГисЭлементСправочника>();
foreach (var element in input)
{
var поляЭлементаСправочника = new List<ГисПолеЭлементаСправочника>();
foreach (var field in element.NsiElementField)
{
CallOnType<Nsi.NsiElementStringFieldType>(field, x =>
{
поляЭлементаСправочника.Add(new ГисПолеЭлементаСправочника()
{
наименование = x.Name,
значение = x.Value
});
});
}
элементыСправочника.Add(new ГисЭлементСправочника()
{
код = element.Code,
гуид = ParseGuid(element.GUID),
актуальный = element.IsActual,
поля = [.. поляЭлементаСправочника],
элементы = element.ChildElement?.Length > 0 ? AdoptNsiElementTypes(element.ChildElement) : null
});
}
return [.. элементыСправочника];
}
}
}

View File

@ -1,36 +0,0 @@
using Hcs.ClientApi.DataTypes;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Hcs.ClientApi.NsiApi
{
public class HcsNsiApi
{
public HcsClientConfig Config { get; private set; }
public HcsNsiApi(HcsClientConfig config)
{
Config = config;
}
/// <summary>
/// Возвращает данные справочников поставщика информации
/// </summary>
/// <param name="regNum">Реестровый номер справочника</param>
/// <param name="token">Токен отмены</param>
/// <returns>Список справочников</returns>
public async Task<IEnumerable<ГисСправочник>> GetNsiItem(int regNum, CancellationToken token = default)
{
try
{
var method = new HcsMethodExportNsi(Config);
return await method.GetNsiItem(regNum, token);
}
catch (HcsNoResultsRemoteException)
{
return [];
}
}
}
}

View File

@ -1,112 +0,0 @@
using Hcs.ClientApi.RemoteCaller;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Nsi = Hcs.Service.Async.Nsi.v15_7_0_1;
namespace Hcs.Service.Async.Nsi.v15_7_0_1
{
public partial class AckRequestAck : IHcsAck { }
public partial class getStateResult : IHcsGetStateResultMany { }
public partial class Fault : IHcsFault { }
public partial class HeaderType : IHcsHeaderType { }
}
namespace Hcs.ClientApi.NsiApi
{
internal class HcsNsiMethod : HcsRemoteCallMethod<IHcsGetStateResultMany>
{
public HcsEndPoints EndPoint => HcsEndPoints.NsiAsync;
public Nsi.RequestHeader CreateRequestHeader() =>
HcsRequestHelper.CreateHeader<Nsi.RequestHeader>(ClientConfig);
public HcsNsiMethod(HcsClientConfig config) : base(config) { }
public System.ServiceModel.EndpointAddress RemoteAddress
=> GetEndpointAddress(HcsConstants.EndPointLocator.GetPath(EndPoint));
private Nsi.NsiPortsTypeAsyncClient NewPortClient()
{
var client = new Nsi.NsiPortsTypeAsyncClient(_binding, RemoteAddress);
ConfigureEndpointCredentials(client.Endpoint, client.ClientCredentials);
return client;
}
public async Task<IHcsGetStateResultMany> SendAndWaitResultAsync(
object request,
Func<Nsi.NsiPortsTypeAsyncClient, Task<IHcsAck>> sender,
CancellationToken token)
{
token.ThrowIfCancellationRequested();
while (true)
{
try
{
return await SendAndWaitResultAsyncImpl(request, sender, token);
}
catch (HcsRestartTimeoutException e)
{
if (!CanBeRestarted) throw new HcsException("Превышен лимит ожидания выполнения запроса", e);
Log($"Перезапускаем запрос типа {request.GetType().Name}...");
}
}
}
private async Task<IHcsGetStateResultMany> SendAndWaitResultAsyncImpl(
object request,
Func<Nsi.NsiPortsTypeAsyncClient, Task<IHcsAck>> sender,
CancellationToken token)
{
if (request == null) throw new ArgumentNullException("Null 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<Nsi.ErrorMessageType>().ToList().ForEach(x =>
{
throw HcsRemoteException.CreateNew(x.ErrorCode, x.Description);
});
return stateResult;
}
/// <summary>
/// Выполняет однократную проверку наличия результата.
/// Возвращает null если результата еще нет.
/// </summary>
protected override async Task<IHcsGetStateResultMany> TryGetResultAsync(IHcsAck sourceAck, CancellationToken token)
{
using (var client = NewPortClient())
{
var requestHeader = HcsRequestHelper.CreateHeader<Nsi.RequestHeader>(_config);
var requestBody = new Nsi.getStateRequest { MessageGUID = sourceAck.MessageGUID };
var response = await client.getStateAsync(requestHeader, requestBody);
var resultBody = response.getStateResult;
if (resultBody.RequestState == HcsAsyncRequestStateTypes.Ready)
{
return resultBody;
}
return null;
}
}
}
}

View File

@ -1,88 +0,0 @@
using Hcs.ClientApi.DataTypes;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using NsiCommon = Hcs.Service.Async.NsiCommon.v15_7_0_1;
namespace Hcs.ClientApi.NsiCommonApi
{
/// <summary>
/// Операции экспорта общих справочников подсистемы НСИ
/// </summary>
internal class HcsMethodExportNsiCommon : HcsNsiCommonMethod
{
public HcsMethodExportNsiCommon(HcsClientConfig config) : base(config)
{
EnableMinimalResponseWaitDelay = true;
CanBeRestarted = true;
}
/// <summary>
/// Возвращает общий справочник подсистемы НСИ
/// </summary>
/// <param name="regNum">Реестровый номер справочника</param>
/// <param name="token">Токен отмены</param>
/// <returns>Справочник</returns>
public async Task<ГисСправочник> GetNsiItem(int regNum, CancellationToken token)
{
var request = new NsiCommon.exportNsiItemRequest
{
Id = HcsConstants.SignedXmlElementId,
RegistryNumber = regNum.ToString(),
// http://open-gkh.ru/NsiCommon/exportNsiItemRequest.html
version = "10.0.1.2"
};
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
{
var response = await portClient.exportNsiItemAsync(CreateRequestHeader(), request);
return response.AckRequest.Ack;
}, token);
return AdoptNsiItemType(stateResult.Item as NsiCommon.NsiItemType);
}
private ГисСправочник AdoptNsiItemType(NsiCommon.NsiItemType input)
{
var справочник = new ГисСправочник()
{
реестровыйНомер = input.NsiItemRegistryNumber,
датаФормирования = input.Created,
элементы = AdoptNsiElementTypes(input.NsiElement)
};
return справочник;
}
private ГисЭлементСправочника[] AdoptNsiElementTypes(NsiCommon.NsiElementType[] input)
{
var элементыСправочника = new List<ГисЭлементСправочника>();
foreach (var element in input)
{
var поляЭлементаСправочника = new List<ГисПолеЭлементаСправочника>();
foreach (var field in element.NsiElementField)
{
CallOnType<NsiCommon.NsiElementStringFieldType>(field, x =>
{
поляЭлементаСправочника.Add(new ГисПолеЭлементаСправочника()
{
наименование = x.Name,
значение = x.Value
});
});
}
элементыСправочника.Add(new ГисЭлементСправочника()
{
код = element.Code,
гуид = ParseGuid(element.GUID),
актуальный = element.IsActual,
поля = [.. поляЭлементаСправочника],
элементы = element.ChildElement?.Length > 0 ? AdoptNsiElementTypes(element.ChildElement) : null
});
}
return [.. элементыСправочника];
}
}
}

View File

@ -1,35 +0,0 @@
using Hcs.ClientApi.DataTypes;
using System.Threading;
using System.Threading.Tasks;
namespace Hcs.ClientApi.NsiCommonApi
{
public class HcsNsiCommonApi
{
public HcsClientConfig Config { get; private set; }
public HcsNsiCommonApi(HcsClientConfig config)
{
Config = config;
}
/// <summary>
/// Возвращает данные справочников поставщика информации
/// </summary>
/// <param name="regNum">Реестровый номер справочника</param>
/// <param name="token">Токен отмены</param>
/// <returns>Список справочников</returns>
public async Task<ГисСправочник> GetNsiItem(int regNum, CancellationToken token = default)
{
try
{
var method = new HcsMethodExportNsiCommon(Config);
return await method.GetNsiItem(regNum, token);
}
catch (HcsNoResultsRemoteException)
{
return null;
}
}
}
}

View File

@ -1,111 +0,0 @@
using Hcs.ClientApi.RemoteCaller;
using System;
using System.Threading;
using System.Threading.Tasks;
using NsiCommon = Hcs.Service.Async.NsiCommon.v15_7_0_1;
namespace Hcs.Service.Async.NsiCommon.v15_7_0_1
{
public partial class AckRequestAck : IHcsAck { }
public partial class getStateResult : IHcsGetStateResultOne { }
public partial class Fault : IHcsFault { }
public partial class HeaderType : IHcsHeaderType { }
}
namespace Hcs.ClientApi.NsiCommonApi
{
internal class HcsNsiCommonMethod : HcsRemoteCallMethod<IHcsGetStateResultOne>
{
public HcsEndPoints EndPoint => HcsEndPoints.NsiCommonAsync;
public NsiCommon.ISRequestHeader CreateRequestHeader() =>
HcsRequestHelper.CreateHeader<NsiCommon.ISRequestHeader>(ClientConfig);
public HcsNsiCommonMethod(HcsClientConfig config) : base(config) { }
public System.ServiceModel.EndpointAddress RemoteAddress
=> GetEndpointAddress(HcsConstants.EndPointLocator.GetPath(EndPoint));
private NsiCommon.NsiPortsTypeAsyncClient NewPortClient()
{
var client = new NsiCommon.NsiPortsTypeAsyncClient(_binding, RemoteAddress);
ConfigureEndpointCredentials(client.Endpoint, client.ClientCredentials);
return client;
}
public async Task<IHcsGetStateResultOne> SendAndWaitResultAsync(
object request,
Func<NsiCommon.NsiPortsTypeAsyncClient, Task<IHcsAck>> sender,
CancellationToken token)
{
token.ThrowIfCancellationRequested();
while (true)
{
try
{
return await SendAndWaitResultAsyncImpl(request, sender, token);
}
catch (HcsRestartTimeoutException e)
{
if (!CanBeRestarted) throw new HcsException("Превышен лимит ожидания выполнения запроса", e);
Log($"Перезапускаем запрос типа {request.GetType().Name}...");
}
}
}
private async Task<IHcsGetStateResultOne> SendAndWaitResultAsyncImpl(
object request,
Func<NsiCommon.NsiPortsTypeAsyncClient, Task<IHcsAck>> sender,
CancellationToken token)
{
if (request == null) throw new ArgumentNullException("Null 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);
if (stateResult.Item is NsiCommon.ErrorMessageType x)
{
throw HcsRemoteException.CreateNew(x.ErrorCode, x.Description);
}
return stateResult;
}
/// <summary>
/// Выполняет однократную проверку наличия результата.
/// Возвращает null если результата еще нет.
/// </summary>
protected override async Task<IHcsGetStateResultOne> TryGetResultAsync(IHcsAck sourceAck, CancellationToken token)
{
using (var client = NewPortClient())
{
var requestHeader = HcsRequestHelper.CreateHeader<NsiCommon.ISRequestHeader>(_config);
var requestBody = new NsiCommon.getStateRequest { MessageGUID = sourceAck.MessageGUID };
var response = await client.getStateAsync(requestHeader, requestBody);
var resultBody = response.getStateResult;
if (resultBody.RequestState == HcsAsyncRequestStateTypes.Ready)
{
return resultBody;
}
return null;
}
}
}
}

View File

@ -1,133 +0,0 @@
using Hcs.ClientApi.DataTypes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using OrgRegistryCommon = Hcs.Service.Async.OrgRegistryCommon.v15_7_0_1;
namespace Hcs.ClientApi.OrgRegistryCommonApi
{
/// <summary>
/// Операции экспорта данных из реестра организаций ГИС ЖКХ
/// </summary>
public class HcsMethodExportOrgRegistry : HcsOrgRegistryCommonMethod
{
public HcsMethodExportOrgRegistry(HcsClientConfig config) : base(config)
{
EnableMinimalResponseWaitDelay = true;
CanBeRestarted = true;
}
/// <summary>
/// Возвращает карточки организации в ГИС ЖКХ по номеру ОГРН организации.
/// При отсутствии результатов будет выброшено HcsNoResultsRemoteException.
/// </summary>
public async Task<IEnumerable<ГисОрганизация>> GetOrgByOgrn(
string ogrn, string kpp, CancellationToken token)
{
if (string.IsNullOrEmpty(ogrn)) throw new ArgumentException("Не указан ОГРН для поиска организации");
if (ogrn.Length != ГисОрганизация.ДлинаОГРН && ogrn.Length != ГисОрганизация.ДлинаОГРНИП)
{
throw new ArgumentException(
$"В строке ОГРН допускается или {ГисОрганизация.ДлинаОГРН} или {ГисОрганизация.ДлинаОГРНИП} символов: {ogrn}");
}
var criteria = new OrgRegistryCommon.exportOrgRegistryRequestSearchCriteria();
if (!string.IsNullOrEmpty(kpp))
{
criteria.ItemsElementName = [OrgRegistryCommon.ItemsChoiceType3.OGRN, OrgRegistryCommon.ItemsChoiceType3.KPP];
criteria.Items = [ogrn, kpp];
}
else
{
if (ogrn.Length == ГисОрганизация.ДлинаОГРНИП)
criteria.ItemsElementName = [OrgRegistryCommon.ItemsChoiceType3.OGRNIP];
else criteria.ItemsElementName = [OrgRegistryCommon.ItemsChoiceType3.OGRN];
criteria.Items = [ogrn];
}
var request = new OrgRegistryCommon.exportOrgRegistryRequest
{
Id = HcsConstants.SignedXmlElementId,
SearchCriteria = [criteria]
};
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
{
var response = await portClient.exportOrgRegistryAsync(CreateRequestHeader(), request);
return response.AckRequest.Ack;
}, token);
// В возвращаемой структуре мало ценной информации, только ГУИД организации в ГИС ЖКХ
// (необходимый для размещения договоров) и ГУИД поставщика информации OrgPPAGUID.
// Для организаций с филиалами может вернуться список из нескольких ГУИД.
return stateResult.Items
.OfType<OrgRegistryCommon.exportOrgRegistryResultType>()
.Select(x => Adopt(x));
}
private ГисОрганизация Adopt(OrgRegistryCommon.exportOrgRegistryResultType orgResult)
{
if (orgResult.OrgVersion == null)
throw new HcsException("В структуре exportOrgRegistryResultType не указано поле OrgVersion");
var организация = new ГисОрганизация()
{
ГуидОрганизации = ParseGuid(orgResult.orgRootEntityGUID),
ГуидВерсииОрганизации = ParseGuid(orgResult.OrgVersion.orgVersionGUID),
Действующая = orgResult.OrgVersion.IsActual
};
switch (orgResult.OrgVersion.Item)
{
case OrgRegistryCommon.LegalType legal:
организация.ТипОрганизации = ГисТипОрганизации.ЮЛ;
организация.ИНН = legal.INN;
организация.КПП = legal.KPP;
организация.ОГРН = legal.OGRN;
организация.ОКОПФ = legal.OKOPF;
организация.КраткоеИмяОрганизации = legal.ShortName;
организация.ПолноеИмяОрганизации = legal.FullName;
организация.ЮридическийАдрес = legal.Address;
if (legal.ActivityEndDateSpecified)
организация.ДатаЛиквидации = legal.ActivityEndDate;
break;
case OrgRegistryCommon.EntpsType entps:
организация.ТипОрганизации = ГисТипОрганизации.ИП;
организация.ИНН = entps.INN;
организация.ОГРН = entps.OGRNIP;
организация.Фамилия = entps.Surname;
организация.Имя = entps.FirstName;
организация.Отчество = entps.Patronymic;
break;
case OrgRegistryCommon.SubsidiaryType sub:
организация.ТипОрганизации = ГисТипОрганизации.Филиал;
организация.ИНН = sub.INN;
организация.КПП = sub.KPP;
организация.ОГРН = sub.OGRN;
организация.ОКОПФ = sub.OKOPF;
организация.КраткоеИмяОрганизации = sub.ShortName;
организация.ПолноеИмяОрганизации = sub.FullName;
организация.ЮридическийАдрес = sub.Address;
if (sub.ActivityEndDateSpecified)
организация.ДатаЛиквидации = sub.ActivityEndDate;
break;
case OrgRegistryCommon.ForeignBranchType foreign:
организация.ТипОрганизации = ГисТипОрганизации.Иностранный;
организация.ИНН = foreign.INN;
организация.КПП = foreign.KPP;
организация.КраткоеИмяОрганизации = foreign.ShortName;
организация.ПолноеИмяОрганизации = foreign.FullName;
организация.ЮридическийАдрес = foreign.Address;
break;
}
return организация;
}
}
}

View File

@ -1,48 +0,0 @@
using Hcs.ClientApi.DataTypes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Hcs.ClientApi.OrgRegistryCommonApi
{
public class HcsOrgRegistryCommonApi
{
public HcsClientConfig Config { get; private set; }
public HcsOrgRegistryCommonApi(HcsClientConfig config)
{
this.Config = config;
}
/// <summary>
/// Возвращает ГУИДы действующих организаций в ГИС ЖКХ по номеру ОГРН (КПП может быть не указан).
/// Если организации не найдены, возвращается пустой список.
/// </summary>
public async Task<IEnumerable<Guid>> GetOrgRootEntityGuidByOgrn(
string ogrn, string kpp, CancellationToken token = default)
{
var orgs = await GetOrgByOgrn(ogrn, kpp, token);
return orgs.Where(x => x.Действующая).Select(x => x.ГуидОрганизации);
}
/// <summary>
/// Возвращает карточки организации в ГИС ЖКХ по номеру ОГРН (КПП может быть не указан).
/// Если организации не найдены, возвращается пустой список.
/// </summary>
public async Task<IEnumerable<ГисОрганизация>> GetOrgByOgrn(
string ogrn, string kpp, CancellationToken token = default)
{
try
{
var method = new HcsMethodExportOrgRegistry(Config);
return await method.GetOrgByOgrn(ogrn, kpp, token);
}
catch (HcsNoResultsRemoteException)
{
return [];
}
}
}
}

View File

@ -1,112 +0,0 @@
using Hcs.ClientApi.RemoteCaller;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using OrgRegistryCommon = Hcs.Service.Async.OrgRegistryCommon.v15_7_0_1;
namespace Hcs.Service.Async.OrgRegistryCommon.v15_7_0_1
{
public partial class AckRequestAck : IHcsAck { }
public partial class getStateResult : IHcsGetStateResultMany { }
public partial class Fault : IHcsFault { }
public partial class HeaderType : IHcsHeaderType { }
}
namespace Hcs.ClientApi.OrgRegistryCommonApi
{
public class HcsOrgRegistryCommonMethod : HcsRemoteCallMethod<IHcsGetStateResultMany>
{
public HcsEndPoints EndPoint => HcsEndPoints.OrgRegistryCommonAsync;
public OrgRegistryCommon.ISRequestHeader CreateRequestHeader() =>
HcsRequestHelper.CreateHeader<OrgRegistryCommon.ISRequestHeader>(ClientConfig);
public HcsOrgRegistryCommonMethod(HcsClientConfig config) : base(config) { }
public System.ServiceModel.EndpointAddress RemoteAddress
=> GetEndpointAddress(HcsConstants.EndPointLocator.GetPath(EndPoint));
private OrgRegistryCommon.RegOrgPortsTypeAsyncClient NewPortClient()
{
var client = new OrgRegistryCommon.RegOrgPortsTypeAsyncClient(_binding, RemoteAddress);
ConfigureEndpointCredentials(client.Endpoint, client.ClientCredentials);
return client;
}
public async Task<IHcsGetStateResultMany> SendAndWaitResultAsync(
object request,
Func<OrgRegistryCommon.RegOrgPortsTypeAsyncClient, Task<IHcsAck>> sender,
CancellationToken token)
{
token.ThrowIfCancellationRequested();
while (true)
{
try
{
return await SendAndWaitResultAsyncImpl(request, sender, token);
}
catch (HcsRestartTimeoutException e)
{
if (!CanBeRestarted) throw new HcsException("Превышен лимит ожидания выполнения запроса", e);
Log($"Перезапускаем запрос типа {request.GetType().Name}...");
}
}
}
private async Task<IHcsGetStateResultMany> SendAndWaitResultAsyncImpl(
object request,
Func<OrgRegistryCommon.RegOrgPortsTypeAsyncClient, Task<IHcsAck>> sender,
CancellationToken token)
{
if (request == null) throw new ArgumentNullException("Null 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<OrgRegistryCommon.ErrorMessageType>().ToList().ForEach(x =>
{
throw HcsRemoteException.CreateNew(x.ErrorCode, x.Description);
});
return stateResult;
}
/// <summary>
/// Выполняет однократную проверку наличия результата.
/// Возвращает null если результата еще нет.
/// </summary>
protected override async Task<IHcsGetStateResultMany> TryGetResultAsync(IHcsAck sourceAck, CancellationToken token)
{
using (var client = NewPortClient())
{
var requestHeader = HcsRequestHelper.CreateHeader<OrgRegistryCommon.ISRequestHeader>(_config);
var requestBody = new OrgRegistryCommon.getStateRequest { MessageGUID = sourceAck.MessageGUID };
var response = await client.getStateAsync(requestHeader, requestBody);
var resultBody = response.getStateResult;
if (resultBody.RequestState == HcsAsyncRequestStateTypes.Ready)
{
return resultBody;
}
return null;
}
}
}
}

View File

@ -1,34 +0,0 @@
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace Hcs.ClientApi.RemoteCaller
{
public class GostSigningEndpointBehavior : IEndpointBehavior
{
private HcsClientConfig clientConfig;
public GostSigningEndpointBehavior(HcsClientConfig clientConfig)
{
this.clientConfig = clientConfig;
}
public void Validate(ServiceEndpoint endpoint)
{
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(
new GostSigningMessageInspector(clientConfig));
}
}
}

View File

@ -1,120 +0,0 @@
using GostXades;
using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Xml;
namespace Hcs.ClientApi.RemoteCaller
{
/// <summary>
/// Фильтр сообщений добавляет в XML сообщение электронную подпись XADES/GOST.
/// </summary>
internal class GostSigningMessageInspector : IClientMessageInspector
{
private HcsClientConfig clientConfig;
public GostSigningMessageInspector(HcsClientConfig clientConfig)
{
this.clientConfig = clientConfig;
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
try
{
string filterHeader = " Фильтр отправки:";
PurgeDebuggerHeaders(ref request);
var messageBody = GetMessageBodyString(ref request, Encoding.UTF8);
if (!messageBody.Contains(HcsConstants.SignedXmlElementId))
{
clientConfig.MaybeCaptureMessage(true, messageBody);
}
else
{
string certInfo = HcsX509Tools.ДатьСтрокуФИОСертификатаСДатойОкончания(clientConfig.Certificate);
clientConfig.Log($"{filterHeader} подписываю сообщение ключем [{certInfo}]...");
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
var service = new GostXadesBesService(clientConfig.CryptoProviderType);
var signedXml = service.Sign(messageBody,
HcsConstants.SignedXmlElementId,
clientConfig.CertificateThumbprint,
clientConfig.CertificatePassword);
stopwatch.Stop();
clientConfig.Log($"{filterHeader} сообщение подписано за {stopwatch.ElapsedMilliseconds}мс.");
clientConfig.MaybeCaptureMessage(true, signedXml);
request = Message.CreateMessage(
XmlReaderFromString(signedXml), int.MaxValue, request.Version);
}
}
catch (Exception ex)
{
string error = $"В {GetType().Name} произошло исключение";
throw new Exception(error, ex);
}
return null;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
clientConfig.MaybeCaptureMessage(false, reply.ToString());
}
private void PurgeDebuggerHeaders(ref Message request)
{
int limit = request.Headers.Count;
for (int i = 0; i < limit; ++i)
{
if (request.Headers[i].Name.Equals("VsDebuggerCausalityData"))
{
request.Headers.RemoveAt(i);
break;
}
}
}
string GetMessageBodyString(ref Message request, Encoding encoding)
{
MessageBuffer mb = request.CreateBufferedCopy(int.MaxValue);
request = mb.CreateMessage();
Stream s = new MemoryStream();
XmlWriter xw = XmlWriter.Create(s);
mb.CreateMessage().WriteMessage(xw);
xw.Flush();
s.Position = 0;
byte[] bXML = new byte[s.Length];
s.Read(bXML, 0, (int)s.Length);
if (bXML[0] != (byte)'<')
{
return encoding.GetString(bXML, 3, bXML.Length - 3);
}
else
{
return encoding.GetString(bXML, 0, bXML.Length);
}
}
XmlReader XmlReaderFromString(String xml)
{
var stream = new MemoryStream();
var writer = new System.IO.StreamWriter(stream);
writer.Write(xml);
writer.Flush();
stream.Position = 0;
return XmlReader.Create(stream);
}
}
}

View File

@ -1,66 +0,0 @@
using System;
namespace Hcs.ClientApi.RemoteCaller
{
/// <summary>
/// Состояние многостраничной выдачи для методов HCS выдыющих длинные списки.
/// Списки выдаются порциями по 100 позиций и в каждой порции указано состояние
/// многостраничной выдачи одним значением - это либо bool со значением true что
/// означает что эта порция последняя IsLastPage, либо это строка содержащая
/// guid объекта начала следующей порции - и этот guid надо указать в запросе
/// чтобы получить следующую порцию.
/// </summary>
public class HcsPagedResultState
{
/// <summary>
/// Состояние указыввает что это последняя страница
/// </summary>
public bool IsLastPage { get; private set; }
/// <summary>
/// Состояние указывает что это не последняя страница и
/// следующая страница начинается с NextGuid
/// </summary>
public Guid NextGuid { get; private set; }
private const string me = nameof(HcsPagedResultState);
public static readonly HcsPagedResultState IsLastPageResultState = new HcsPagedResultState(true);
/// <summary>
/// Новый маркер состояния многостраничной выдачи метода HCS
/// </summary>
public HcsPagedResultState(object item)
{
if (item == null) throw new HcsException($"{me}.Item is null");
if (item is bool)
{
if ((bool)item == false) throw new HcsException($"{me}.IsLastPage is false");
IsLastPage = true;
}
else if (item is string)
{
try
{
IsLastPage = false;
NextGuid = HcsUtil.ParseGuid((string)item);
}
catch (Exception e)
{
throw new HcsException($"Failed to parse {me}.NextGuid value", e);
}
}
else
{
throw new HcsException($"{me}.Item is of unrecognized type " + item.GetType().FullName);
}
}
public override string ToString()
{
return $"{me}({nameof(IsLastPage)}={IsLastPage}" +
(IsLastPage ? "" : $",{nameof(NextGuid)}={NextGuid}") + ")";
}
}
}

View File

@ -1,373 +0,0 @@
using System;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Hcs.ClientApi.RemoteCaller
{
/// <summary>
/// Базовый класс для методов HCS вызываемых удаленно
/// </summary>
public abstract class HcsRemoteCallMethod<T> where T : IHcsGetStateResult
{
public HcsClientConfig _config;
protected CustomBinding _binding;
/// <summary>
/// Для методов возвращающих мало данных можно попробовать сократить
/// начальный период ожидания подготовки ответа
/// </summary>
public bool EnableMinimalResponseWaitDelay { get; internal set; }
/// <summary>
/// Для противодействия зависанию ожидания вводится предел ожидания в минутах
/// для методов которые можно перезапустить заново с теми же параметрами.
/// С периодом в 120 минут 09.2024 не успевали за ночь получить все данные.
/// </summary>
public int RestartTimeoutMinutes = 20;
/// <summary>
/// Можно ли этот метод перезапускать в случае зависания ожидания или в случае сбоя на сервере?
/// </summary>
public bool CanBeRestarted { get; protected set; }
public HcsClientConfig ClientConfig => _config;
public HcsRemoteCallMethod(HcsClientConfig config)
{
this._config = config;
ConfigureBinding();
}
private void ConfigureBinding()
{
_binding = new CustomBinding();
// Эксперимент 19.07.2022 возникает ошибка WCF (TimeoutException 60 сек)
_binding.ReceiveTimeout = TimeSpan.FromSeconds(180);
_binding.OpenTimeout = TimeSpan.FromSeconds(180);
_binding.SendTimeout = TimeSpan.FromSeconds(180);
_binding.CloseTimeout = TimeSpan.FromSeconds(180);
_binding.Elements.Add(new TextMessageEncodingBindingElement
{
MessageVersion = MessageVersion.Soap11,
WriteEncoding = Encoding.UTF8
});
if (_config.UseTunnel)
{
if (System.Diagnostics.Process.GetProcessesByName("stunnel").Any() ? false : true)
{
throw new Exception("stunnel не запущен");
}
_binding.Elements.Add(new HttpTransportBindingElement
{
AuthenticationScheme = (_config.IsPPAK ? System.Net.AuthenticationSchemes.Digest : System.Net.AuthenticationSchemes.Basic),
MaxReceivedMessageSize = int.MaxValue,
UseDefaultWebProxy = false
});
}
else
{
_binding.Elements.Add(new HttpsTransportBindingElement
{
AuthenticationScheme = (_config.IsPPAK ? System.Net.AuthenticationSchemes.Digest : System.Net.AuthenticationSchemes.Basic),
MaxReceivedMessageSize = int.MaxValue,
UseDefaultWebProxy = false,
RequireClientCertificate = true
});
}
}
protected EndpointAddress GetEndpointAddress(string endpointName)
{
return new EndpointAddress(_config.ComposeEndpointUri(endpointName));
}
protected void ConfigureEndpointCredentials(
ServiceEndpoint serviceEndpoint, ClientCredentials clientCredentials)
{
serviceEndpoint.EndpointBehaviors.Add(new GostSigningEndpointBehavior(_config));
if (!_config.IsPPAK)
{
clientCredentials.UserName.UserName = HcsConstants.UserAuth.Name;
clientCredentials.UserName.Password = HcsConstants.UserAuth.Passwd;
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate (
object sender, X509Certificate serverCertificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
return true;
};
}
else
{
bool letSystemValidateServerCertificate = false;
if (!letSystemValidateServerCertificate)
{
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate (
object sender, X509Certificate serverCertificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
// 06.06.2024 возникла ошибка "Это может быть связано с тем, что сертификат сервера
// не настроен должным образом с помощью HTTP.SYS в случае HTTPS."
// ГИС ЖКХ заменил сертификат сервера HTTPS и System.Net не смогла проверить новый.
// В похожем случае необходимо включить "return true" чтобы любой сертификат
// без проверки принимался (или найти файл lk_api_dom_gosuslugi_ru.cer нового сертификата
// сервера ГИС ЖКХ API в разделе "Регламенты и инструкции" портала dom.gosuslugi.ru
// и установить этот сертификат текущему пользователю).
// Файл сертификата сервера API в разделе "Регламенты и инструкции" называется, например, так:
// "Сертификат открытого ключа для организации защищенного TLS соединения с сервисами
// легковесной интеграции (c 10.06.2024)".
return true;
};
}
}
if (!_config.UseTunnel)
{
clientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.My,
X509FindType.FindByThumbprint,
_config.CertificateThumbprint);
}
}
/// <summary>
/// Выполнение одной попытки пооучить результат операции.
/// Реализуется в производных классах.
/// </summary>
protected abstract Task<T> TryGetResultAsync(IHcsAck sourceAck, CancellationToken token);
/// <summary>
/// Основной алгоритм ожидания ответа на асинхронный запрос.
/// Из документации ГИС ЖКХ:
/// Также рекомендуем придерживаться следующего алгоритма отправки запросов на получение статуса обработки пакета в случае использования асинхронных сервисов ГИС ЖКХ (в рамках одного MessageGUID):
/// - первый запрос getState направлять не ранее чем через 10 секунд, после получения квитанции о приеме пакета с бизнес-данными от сервиса ГИС КЖХ;
/// - в случае, если на первый запрос getSate получен результат с RequestState равным "1" или "2", то следующий запрос getState необходимо направлять не ранее чем через 60 секунд после отправки предыдущего запроса;
/// - в случае, если на второй запрос getSate получен результат с RequestState равным "1" или "2", то следующий запрос getState необходимо направлять не ранее чем через 300 секунд после отправки предыдущего запроса;
/// - в случае, если на третий запрос getSate получен результат с RequestState равным "1" или "2", то следующий запрос getState необходимо направлять не ранее чем через 900 секунд после отправки предыдущего запроса;
/// - в случае, если на четвертый(и все последующие запросы) getState получен результат с RequestState равным "1" или "2", то следующий запрос getState необходимо направлять не ранее чем через 1800 секунд после отправки предыдущего запроса.
/// </summary>
protected async Task<T> WaitForResultAsync(
IHcsAck ack, bool withInitialDelay, CancellationToken token)
{
var startTime = DateTime.Now;
T result;
for (int attempts = 1; ; attempts++)
{
token.ThrowIfCancellationRequested();
int delaySec = EnableMinimalResponseWaitDelay ? 2 : 5;
if (attempts >= 2) delaySec = 5;
if (attempts >= 3) delaySec = 10;
if (attempts >= 5) delaySec = 20;
if (attempts >= 7) delaySec = 40;
if (attempts >= 9) delaySec = 80;
if (attempts >= 12) delaySec = 300;
if (attempts > 1 || withInitialDelay)
{
var minutesElapsed = (int)(DateTime.Now - startTime).TotalMinutes;
if (CanBeRestarted && minutesElapsed > RestartTimeoutMinutes)
throw new HcsRestartTimeoutException($"Превышено ожидание в {RestartTimeoutMinutes} минут");
_config.Log($"Ожидаю {delaySec} сек. до попытки #{attempts}" +
$" получить ответ (ожидание {minutesElapsed} минут(ы))...");
await Task.Delay(delaySec * 1000, token);
}
_config.Log($"Запрашиваю ответ, попытка #{attempts} {ThreadIdText}...");
result = await TryGetResultAsync(ack, token);
if (result != null) break;
}
_config.Log($"Ответ получен");
return result;
}
/// <summary>
/// Исполнение повторяемой операции некоторое дпустимое число ошибок
/// </summary>
public async Task<T> RunRepeatableTaskAsync<T>(
Func<Task<T>> taskFunc, Func<Exception, bool> canIgnoreFunc, int maxAttempts)
{
for (int attempts = 1; ; attempts++)
{
try
{
return await taskFunc();
}
catch (Exception e)
{
if (canIgnoreFunc(e))
{
if (attempts < maxAttempts)
{
Log($"Игнорирую {attempts} из {maxAttempts} допустимых ошибок");
continue;
}
throw new HcsException(
$"Более {maxAttempts} продолжений после допустимых ошибок", e);
}
throw new HcsException("Вложенная ошибка", e);
}
}
}
/// <summary>
/// Для запросов к серверу которые можно направлять несколько раз, разрешаем
/// серверу аномально отказаться. Предполагается, что здесь мы игнорируем
/// только жесткие отказы серверной инфраструктуры, которые указывают
/// что запрос даже не был принят в обработку. Также все запросы на
/// чтение можно повторять в случае их серверных системных ошибок.
/// </summary>
protected async Task<T> RunRepeatableTaskInsistentlyAsync<T>(
Func<Task<T>> func, CancellationToken token)
{
int afterErrorDelaySec = 120;
for (int attempt = 1; ; attempt++)
{
try
{
return await func();
}
catch (Exception e)
{
string marker;
if (CanIgnoreSuchException(e, out marker))
{
_config.Log($"Игнорирую ошибку #{attempt} типа [{marker}].");
_config.Log($"Ожидаю {afterErrorDelaySec} сек. до повторения после ошибки...");
await Task.Delay(afterErrorDelaySec * 1000, token);
continue;
}
if (e is HcsRestartTimeoutException)
throw new HcsRestartTimeoutException("Наступило событие рестарта", e);
// Ошибки удаленной системы, которые нельзя игнорировать, дублируем для точности перехвата
if (e is HcsRemoteException) throw HcsRemoteException.CreateNew(e as HcsRemoteException);
throw new HcsException("Ошибка, которую нельзя игнорировать", e);
}
}
}
// "[EXP001000] Произошла ошибка при передаче данных. Попробуйте осуществить передачу данных повторно",
// Видимо, эту ошибку нельзя включать здесь. Предположительно это маркер DDOS защиты и если отправлять
// точно такой же пакет повторно, то ошибка входит в бесконечный цикл - необходимо заново
// собирать пакет с новыми кодами и временем и новой подписью. Такую ошибку надо обнаруживать
// на более высоком уровне и заново отправлять запрос новым пакетом. (21.09.2022)
private static string[] ignorableSystemErrorMarkers = {
"Истекло время ожидания шлюза",
"Базовое соединение закрыто: Соединение, которое должно было работать, было разорвано сервером",
"Попробуйте осуществить передачу данных повторно", // Включено 18.10.2024, HouseManagement API сильно сбоит
"(502) Недопустимый шлюз",
"(503) Сервер не доступен"
};
private bool CanIgnoreSuchException(Exception e, out string resultMarker)
{
foreach (var marker in ignorableSystemErrorMarkers)
{
var found = HcsUtil.EnumerateInnerExceptions(e).Find(
x => x.Message != null && x.Message.Contains(marker));
if (found != null)
{
resultMarker = marker;
return true;
}
}
resultMarker = null;
return false;
}
/// <summary>
/// Проверяет массив @items на содержание строго одного элемента типа @T и этот элемент
/// </summary>
protected T RequireSingleItem<T>(object[] items)
{
if (items == null)
throw new HcsException($"Array of type {typeof(T)} must not be null");
if (items.Length == 0)
throw new HcsException($"Array of type {typeof(T)} must not be empty");
if (items.Length > 1)
throw new HcsException($"Array of type {typeof(T)} must contain 1 element, not {items.Length} of type {items[0].GetType().FullName}");
return RequireType<T>(items[0]);
}
/// <summary>
/// Проверяет @obj на соответствие типу @T и возвращает преобразованный объект
/// </summary>
protected T RequireType<T>(object obj)
{
if (obj != null)
{
if (typeof(T) == obj.GetType()) return (T)obj;
}
throw new HcsException(
$"Require object of type {typeof(T)} but got" +
(obj == null ? "null" : obj.GetType().FullName));
}
internal static HcsException NewUnexpectedObjectException(object obj)
{
if (obj == null) return new HcsException("unexpected object is null");
return new HcsException($"Unexpected object [{obj}] of type {obj.GetType().FullName}");
}
public static string FormatGuid(Guid guid) => HcsUtil.FormatGuid(guid);
public static string FormatGuid(Guid? guid) => (guid != null) ? FormatGuid((Guid)guid) : null;
public static Guid ParseGuid(string guid) => HcsUtil.ParseGuid(guid);
public static Guid ParseGuid(object obj)
{
if (obj == null) throw new HcsException("Can't parse null as Guid");
if (obj is Guid) return (Guid)obj;
return ParseGuid(obj.ToString());
}
public static Guid[] ParseGuidArray(string[] array)
{
if (array == null) return null;
return array.ToList().Select(x => ParseGuid(x)).ToArray();
}
public bool IsArrayEmpty(Array a) => (a == null || a.Length == 0);
public string MakeEmptyNull(string s)
{
return string.IsNullOrEmpty(s) ? null : s;
}
/// <summary>
/// Выполняет @action на объекте @x если объект не пустой и приводится к типу @T
/// </summary>
public void CallOnType<T>(object x, Action<T> action) where T : class
{
var t = x as T;
if (t != null) action(t);
}
/// <summary>
/// Возвращает индентификатор текущего исполняемого потока
/// </summary>
public int ThreadId => System.Environment.CurrentManagedThreadId;
public string ThreadIdText => $"(thread #{ThreadId})";
public void Log(string message) => ClientConfig.Log(message);
}
}

View File

@ -1,84 +0,0 @@
using System;
using System.Linq;
namespace Hcs.ClientApi.RemoteCaller
{
public static class HcsRequestHelper
{
/// <summary>
/// Подготовка заголовка сообщения отправляемого в ГИС ЖКХ с обязательными атрибутами.
/// Заголовки могут быть разного типа для разных типов сообщений но имена полей одинаковые.
/// </summary>
public static THeaderType CreateHeader<THeaderType>(HcsClientConfig config) where THeaderType : class
{
try
{
var instance = Activator.CreateInstance(typeof(THeaderType));
foreach (var prop in instance.GetType().GetProperties())
{
switch (prop.Name)
{
case "Item":
prop.SetValue(instance, config.OrgPPAGUID);
break;
case "ItemElementName":
prop.SetValue(instance, Enum.Parse(prop.PropertyType, "orgPPAGUID"));
break;
case "MessageGUID":
prop.SetValue(instance, Guid.NewGuid().ToString());
break;
case "Date":
prop.SetValue(instance, DateTime.Now);
break;
case "IsOperatorSignatureSpecified":
if (config.Role == HcsOrganizationRoles.RC || config.Role == HcsOrganizationRoles.RSO)
prop.SetValue(instance, true);
break;
case "IsOperatorSignature":
if (config.Role == HcsOrganizationRoles.RC || config.Role == HcsOrganizationRoles.RSO)
prop.SetValue(instance, true);
break;
}
}
return instance as THeaderType;
}
catch (ArgumentNullException ex)
{
throw new ApplicationException($"При сборке заголовка запроса для ГИС произошла ошибка: {ex.Message}");
}
catch (SystemException exc)
{
throw new ApplicationException($"При сборке заголовка запроса для ГИС произошла не предвиденная ошибка {exc.GetBaseException().Message}");
}
}
/// <summary>
/// Для объекта запроса возвращает значение строки свойства version
/// </summary>
public static string GetRequestVersionString(object requestObject)
{
if (requestObject == null) return null;
object versionHost = requestObject;
if (versionHost != null)
{
var versionProperty = versionHost.GetType().GetProperties().FirstOrDefault(x => x.Name == "version");
if (versionProperty != null) return versionProperty.GetValue(versionHost) as string;
}
foreach (var field in requestObject.GetType().GetFields())
{
versionHost = field.GetValue(requestObject);
if (versionHost != null)
{
var versionProperty = versionHost.GetType().GetProperties().FirstOrDefault(x => x.Name == "version");
if (versionProperty != null) return versionProperty.GetValue(versionHost) as string;
}
}
return null;
}
}
}

View File

@ -1,18 +0,0 @@
namespace Hcs.ClientApi.RemoteCaller
{
/// <summary>
/// Конфигурация ServicePointManager для работы с TLS. Скорее всего класс не нужен.
/// </summary>
public static class HcsServicePointConfig
{
public static void InitConfig()
{
// TODO: Проверить комментарий
// Отключено 15.12.2023, работает и так
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
//ServicePointManager.CheckCertificateRevocationList = false;
//ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true);
//ServicePointManager.Expect100Continue = false;
}
}
}

View File

@ -1,8 +0,0 @@
namespace Hcs.ClientApi.RemoteCaller
{
public interface IHcsAck
{
string MessageGUID { get; set; }
string RequesterMessageGUID { get; set; }
}
}

View File

@ -1,8 +0,0 @@
namespace Hcs.ClientApi.RemoteCaller
{
public interface IHcsFault
{
string ErrorCode { get; set; }
string ErrorMessage { get; set; }
}
}

View File

@ -1,7 +0,0 @@
namespace Hcs.ClientApi.RemoteCaller
{
/// <summary>
/// Интерфейс-маркер
/// </summary>
public interface IHcsGetStateResult { }
}

View File

@ -1,7 +0,0 @@
namespace Hcs.ClientApi.RemoteCaller
{
public interface IHcsGetStateResultMany : IHcsGetStateResult
{
object[] Items { get; set; }
}
}

View File

@ -1,7 +0,0 @@
namespace Hcs.ClientApi.RemoteCaller
{
public interface IHcsGetStateResultOne : IHcsGetStateResult
{
object Item { get; set; }
}
}

View File

@ -1,10 +0,0 @@
using System;
namespace Hcs.ClientApi.RemoteCaller
{
public interface IHcsHeaderType
{
string MessageGUID { get; set; }
DateTime Date { get; set; }
}
}

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="AckRequest" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>Hcs.Service.Async.DebtRequests.v15_7_0_1.AckRequest, Connected Services.Service.Async.DebtRequests.v15_7_0_1.Reference.cs.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="ResultHeader" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>Hcs.Service.Async.DebtRequests.v15_7_0_1.ResultHeader, Connected Services.Service.Async.DebtRequests.v15_7_0_1.Reference.cs.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="exportDebtRequestsResponse" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>Hcs.Service.Async.DebtRequests.v15_7_0_1.exportDebtRequestsResponse, Connected Services.Service.Async.DebtRequests.v15_7_0_1.Reference.cs.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="exportDebtSubrequestsResponse" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>Hcs.Service.Async.DebtRequests.v15_7_0_1.exportDebtSubrequestsResponse, Connected Services.Service.Async.DebtRequests.v15_7_0_1.Reference.cs.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="getStateResponse" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>Hcs.Service.Async.DebtRequests.v15_7_0_1.getStateResponse, Connected Services.Service.Async.DebtRequests.v15_7_0_1.Reference.cs.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="getStateResult" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>Hcs.Service.Async.DebtRequests.v15_7_0_1.getStateResult, Connected Services.Service.Async.DebtRequests.v15_7_0_1.Reference.cs.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="importDebtRequestsResponse" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>Hcs.Service.Async.DebtRequests.v15_7_0_1.importDebtRequestsResponse, Connected Services.Service.Async.DebtRequests.v15_7_0_1.Reference.cs.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="importResponsesResponse" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>Hcs.Service.Async.DebtRequests.v15_7_0_1.importResponsesResponse, Connected Services.Service.Async.DebtRequests.v15_7_0_1.Reference.cs.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ReferenceGroup xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ID="b642da62-3cd9-49d7-b257-5a2a6b4baeb7" xmlns="urn:schemas-microsoft-com:xml-wcfservicemap">
<ClientOptions>
<GenerateAsynchronousMethods>false</GenerateAsynchronousMethods>
<GenerateTaskBasedAsynchronousMethod>true</GenerateTaskBasedAsynchronousMethod>
<EnableDataBinding>true</EnableDataBinding>
<ExcludedTypes />
<ImportXmlTypes>false</ImportXmlTypes>
<GenerateInternalTypes>false</GenerateInternalTypes>
<GenerateMessageContracts>false</GenerateMessageContracts>
<NamespaceMappings />
<CollectionMappings />
<GenerateSerializableTypes>true</GenerateSerializableTypes>
<Serializer>Auto</Serializer>
<UseSerializerForFaults>true</UseSerializerForFaults>
<ReferenceAllAssemblies>true</ReferenceAllAssemblies>
<ReferencedAssemblies />
<ReferencedDataContractTypes />
<ServiceContractMappings />
</ClientOptions>
<MetadataSources>
<MetadataSource Address="C:\Users\kshkulev\Documents\hcs\Hcs.Client\HcsWsdlSources\wsdl_xsd_v.15.7.0.1\debt-requests\hcs-debt-requests-service-async.wsdl" Protocol="file" SourceId="1" />
</MetadataSources>
<Metadata>
<MetadataFile FileName="hcs-nsi-base.xsd" MetadataType="Schema" ID="22c761cf-4124-40b5-8db6-a7793d47c2f9" SourceId="1" SourceUrl="file:///C:/Users/kshkulev/Documents/hcs/Hcs.Client/HcsWsdlSources/wsdl_xsd_v.15.7.0.1/lib/hcs-nsi-base.xsd" />
<MetadataFile FileName="hcs-debt-requests-service-async.wsdl" MetadataType="Wsdl" ID="0bfa5b2a-a70a-4704-8ca7-ef026e309351" SourceId="1" SourceUrl="file:///C:/Users/kshkulev/Documents/hcs/Hcs.Client/HcsWsdlSources/wsdl_xsd_v.15.7.0.1/debt-requests/hcs-debt-requests-service-async.wsdl" />
<MetadataFile FileName="hcs-base.xsd" MetadataType="Schema" ID="82b9f743-c490-4475-b15f-e3356126b76f" SourceId="1" SourceUrl="file:///C:/Users/kshkulev/Documents/hcs/Hcs.Client/HcsWsdlSources/wsdl_xsd_v.15.7.0.1/lib/hcs-base.xsd" />
<MetadataFile FileName="xmldsig-core-schema.xsd" MetadataType="Schema" ID="5beb2945-bc64-4c54-bffe-c7ac02e14e5f" SourceId="1" SourceUrl="file:///C:/Users/kshkulev/Documents/hcs/Hcs.Client/HcsWsdlSources/wsdl_xsd_v.15.7.0.1/lib/xmldsig-core-schema.xsd" />
<MetadataFile FileName="hcs-debt-requests-types.xsd" MetadataType="Schema" ID="64971bf4-fd3d-4ee6-b3f0-7019e4185b38" SourceId="1" SourceUrl="file:///C:/Users/kshkulev/Documents/hcs/Hcs.Client/HcsWsdlSources/wsdl_xsd_v.15.7.0.1/debt-requests/hcs-debt-requests-types.xsd" />
</Metadata>
<Extensions>
<ExtensionFile FileName="configuration91.svcinfo" Name="configuration91.svcinfo" />
<ExtensionFile FileName="configuration.svcinfo" Name="configuration.svcinfo" />
</Extensions>
</ReferenceGroup>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configurationSnapshot xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:schemas-microsoft-com:xml-wcfconfigurationsnapshot">
<behaviors />
<bindings>
<binding digest="System.ServiceModel.Configuration.BasicHttpBindingElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089:&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;&lt;Data name=&quot;DebtRequestsAsyncBinding&quot;&gt;&lt;security mode=&quot;Transport&quot; /&gt;&lt;/Data&gt;" bindingType="basicHttpBinding" name="DebtRequestsAsyncBinding" />
<binding digest="System.ServiceModel.Configuration.BasicHttpBindingElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089:&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;&lt;Data name=&quot;DebtRequestsAsyncBinding1&quot; /&gt;" bindingType="basicHttpBinding" name="DebtRequestsAsyncBinding1" />
</bindings>
<endpoints>
<endpoint normalizedDigest="&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;&lt;Data address=&quot;https://api.dom.gosuslugi.ru/ext-bus-debtreq-service/services/DebtRequestsAsync&quot; binding=&quot;basicHttpBinding&quot; bindingConfiguration=&quot;DebtRequestsAsyncBinding&quot; contract=&quot;Service.Async.DebtRequests.v15_7_0_1.DebtRequestsAsyncPort&quot; name=&quot;DebtRequestsAsyncPort&quot; /&gt;" digest="&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;&lt;Data address=&quot;https://api.dom.gosuslugi.ru/ext-bus-debtreq-service/services/DebtRequestsAsync&quot; binding=&quot;basicHttpBinding&quot; bindingConfiguration=&quot;DebtRequestsAsyncBinding&quot; contract=&quot;Service.Async.DebtRequests.v15_7_0_1.DebtRequestsAsyncPort&quot; name=&quot;DebtRequestsAsyncPort&quot; /&gt;" contractName="Service.Async.DebtRequests.v15_7_0_1.DebtRequestsAsyncPort" name="DebtRequestsAsyncPort" />
</endpoints>
</configurationSnapshot>

View File

@ -1,310 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<SavedWcfConfigurationInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="9.1" CheckSum="ULifDpf43Y229cZbpvxlIfRDy2V+0bJ32OpepzDCUtY=">
<bindingConfigurations>
<bindingConfiguration bindingType="basicHttpBinding" name="DebtRequestsAsyncBinding">
<properties>
<property path="/name" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>DebtRequestsAsyncBinding</serializedValue>
</property>
<property path="/closeTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/openTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/receiveTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/sendTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/allowCookies" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/bypassProxyOnLocal" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/hostNameComparisonMode" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.HostNameComparisonMode, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>StrongWildcard</serializedValue>
</property>
<property path="/maxBufferPoolSize" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/maxBufferSize" isComplexType="false" isExplicitlyDefined="false" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>65536</serializedValue>
</property>
<property path="/maxReceivedMessageSize" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/proxyAddress" isComplexType="false" isExplicitlyDefined="false" clrType="System.Uri, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/readerQuotas" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.XmlDictionaryReaderQuotasElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.XmlDictionaryReaderQuotasElement</serializedValue>
</property>
<property path="/readerQuotas/maxDepth" isComplexType="false" isExplicitlyDefined="false" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>0</serializedValue>
</property>
<property path="/readerQuotas/maxStringContentLength" isComplexType="false" isExplicitlyDefined="false" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>0</serializedValue>
</property>
<property path="/readerQuotas/maxArrayLength" isComplexType="false" isExplicitlyDefined="false" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>0</serializedValue>
</property>
<property path="/readerQuotas/maxBytesPerRead" isComplexType="false" isExplicitlyDefined="false" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>0</serializedValue>
</property>
<property path="/readerQuotas/maxNameTableCharCount" isComplexType="false" isExplicitlyDefined="false" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>0</serializedValue>
</property>
<property path="/textEncoding" isComplexType="false" isExplicitlyDefined="false" clrType="System.Text.Encoding, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.Text.UTF8Encoding</serializedValue>
</property>
<property path="/transferMode" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.TransferMode, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>Buffered</serializedValue>
</property>
<property path="/useDefaultWebProxy" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/messageEncoding" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.WSMessageEncoding, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>Text</serializedValue>
</property>
<property path="/security" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.BasicHttpSecurityElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.BasicHttpSecurityElement</serializedValue>
</property>
<property path="/security/mode" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.BasicHttpSecurityMode, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>Transport</serializedValue>
</property>
<property path="/security/transport" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.HttpTransportSecurityElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.HttpTransportSecurityElement</serializedValue>
</property>
<property path="/security/transport/clientCredentialType" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.HttpClientCredentialType, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>None</serializedValue>
</property>
<property path="/security/transport/proxyCredentialType" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.HttpProxyCredentialType, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>None</serializedValue>
</property>
<property path="/security/transport/extendedProtectionPolicy" isComplexType="true" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.Configuration.ExtendedProtectionPolicyElement, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.Security.Authentication.ExtendedProtection.Configuration.ExtendedProtectionPolicyElement</serializedValue>
</property>
<property path="/security/transport/extendedProtectionPolicy/policyEnforcement" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.PolicyEnforcement, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>Never</serializedValue>
</property>
<property path="/security/transport/extendedProtectionPolicy/protectionScenario" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.ProtectionScenario, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>TransportSelected</serializedValue>
</property>
<property path="/security/transport/extendedProtectionPolicy/customServiceNames" isComplexType="true" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.Configuration.ServiceNameElementCollection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>(Коллекция)</serializedValue>
</property>
<property path="/security/transport/realm" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/security/message" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.BasicHttpMessageSecurityElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.BasicHttpMessageSecurityElement</serializedValue>
</property>
<property path="/security/message/clientCredentialType" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.BasicHttpMessageCredentialType, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>UserName</serializedValue>
</property>
<property path="/security/message/algorithmSuite" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.Security.SecurityAlgorithmSuite, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>Default</serializedValue>
</property>
</properties>
</bindingConfiguration>
<bindingConfiguration bindingType="basicHttpBinding" name="DebtRequestsAsyncBinding1">
<properties>
<property path="/name" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>DebtRequestsAsyncBinding1</serializedValue>
</property>
<property path="/closeTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/openTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/receiveTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/sendTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/allowCookies" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/bypassProxyOnLocal" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/hostNameComparisonMode" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.HostNameComparisonMode, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>StrongWildcard</serializedValue>
</property>
<property path="/maxBufferPoolSize" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/maxBufferSize" isComplexType="false" isExplicitlyDefined="false" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>65536</serializedValue>
</property>
<property path="/maxReceivedMessageSize" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/proxyAddress" isComplexType="false" isExplicitlyDefined="false" clrType="System.Uri, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/readerQuotas" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.XmlDictionaryReaderQuotasElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.XmlDictionaryReaderQuotasElement</serializedValue>
</property>
<property path="/readerQuotas/maxDepth" isComplexType="false" isExplicitlyDefined="false" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>0</serializedValue>
</property>
<property path="/readerQuotas/maxStringContentLength" isComplexType="false" isExplicitlyDefined="false" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>0</serializedValue>
</property>
<property path="/readerQuotas/maxArrayLength" isComplexType="false" isExplicitlyDefined="false" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>0</serializedValue>
</property>
<property path="/readerQuotas/maxBytesPerRead" isComplexType="false" isExplicitlyDefined="false" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>0</serializedValue>
</property>
<property path="/readerQuotas/maxNameTableCharCount" isComplexType="false" isExplicitlyDefined="false" clrType="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>0</serializedValue>
</property>
<property path="/textEncoding" isComplexType="false" isExplicitlyDefined="false" clrType="System.Text.Encoding, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.Text.UTF8Encoding</serializedValue>
</property>
<property path="/transferMode" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.TransferMode, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>Buffered</serializedValue>
</property>
<property path="/useDefaultWebProxy" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/messageEncoding" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.WSMessageEncoding, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>Text</serializedValue>
</property>
<property path="/security" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.BasicHttpSecurityElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.BasicHttpSecurityElement</serializedValue>
</property>
<property path="/security/mode" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.BasicHttpSecurityMode, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>None</serializedValue>
</property>
<property path="/security/transport" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.HttpTransportSecurityElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.HttpTransportSecurityElement</serializedValue>
</property>
<property path="/security/transport/clientCredentialType" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.HttpClientCredentialType, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>None</serializedValue>
</property>
<property path="/security/transport/proxyCredentialType" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.HttpProxyCredentialType, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>None</serializedValue>
</property>
<property path="/security/transport/extendedProtectionPolicy" isComplexType="true" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.Configuration.ExtendedProtectionPolicyElement, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.Security.Authentication.ExtendedProtection.Configuration.ExtendedProtectionPolicyElement</serializedValue>
</property>
<property path="/security/transport/extendedProtectionPolicy/policyEnforcement" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.PolicyEnforcement, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>Never</serializedValue>
</property>
<property path="/security/transport/extendedProtectionPolicy/protectionScenario" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.ProtectionScenario, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>TransportSelected</serializedValue>
</property>
<property path="/security/transport/extendedProtectionPolicy/customServiceNames" isComplexType="true" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.Configuration.ServiceNameElementCollection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>(Коллекция)</serializedValue>
</property>
<property path="/security/transport/realm" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/security/message" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.BasicHttpMessageSecurityElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.BasicHttpMessageSecurityElement</serializedValue>
</property>
<property path="/security/message/clientCredentialType" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.BasicHttpMessageCredentialType, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>UserName</serializedValue>
</property>
<property path="/security/message/algorithmSuite" isComplexType="false" isExplicitlyDefined="false" clrType="System.ServiceModel.Security.SecurityAlgorithmSuite, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>Default</serializedValue>
</property>
</properties>
</bindingConfiguration>
</bindingConfigurations>
<endpoints>
<endpoint name="DebtRequestsAsyncPort" contract="Service.Async.DebtRequests.v15_7_0_1.DebtRequestsAsyncPort" bindingType="basicHttpBinding" address="https://api.dom.gosuslugi.ru/ext-bus-debtreq-service/services/DebtRequestsAsync" bindingConfiguration="DebtRequestsAsyncBinding">
<properties>
<property path="/address" isComplexType="false" isExplicitlyDefined="true" clrType="System.Uri, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>https://api.dom.gosuslugi.ru/ext-bus-debtreq-service/services/DebtRequestsAsync</serializedValue>
</property>
<property path="/behaviorConfiguration" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/binding" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>basicHttpBinding</serializedValue>
</property>
<property path="/bindingConfiguration" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>DebtRequestsAsyncBinding</serializedValue>
</property>
<property path="/contract" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>Service.Async.DebtRequests.v15_7_0_1.DebtRequestsAsyncPort</serializedValue>
</property>
<property path="/headers" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.AddressHeaderCollectionElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.AddressHeaderCollectionElement</serializedValue>
</property>
<property path="/headers/headers" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.Channels.AddressHeaderCollection, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>&lt;Header /&gt;</serializedValue>
</property>
<property path="/identity" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.IdentityElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.IdentityElement</serializedValue>
</property>
<property path="/identity/userPrincipalName" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.UserPrincipalNameElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.UserPrincipalNameElement</serializedValue>
</property>
<property path="/identity/userPrincipalName/value" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/identity/servicePrincipalName" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.ServicePrincipalNameElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.ServicePrincipalNameElement</serializedValue>
</property>
<property path="/identity/servicePrincipalName/value" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/identity/dns" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.DnsElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.DnsElement</serializedValue>
</property>
<property path="/identity/dns/value" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/identity/rsa" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.RsaElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.RsaElement</serializedValue>
</property>
<property path="/identity/rsa/value" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/identity/certificate" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.CertificateElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.CertificateElement</serializedValue>
</property>
<property path="/identity/certificate/encodedValue" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/identity/certificateReference" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.CertificateReferenceElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>System.ServiceModel.Configuration.CertificateReferenceElement</serializedValue>
</property>
<property path="/identity/certificateReference/storeName" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Cryptography.X509Certificates.StoreName, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>My</serializedValue>
</property>
<property path="/identity/certificateReference/storeLocation" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Cryptography.X509Certificates.StoreLocation, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>LocalMachine</serializedValue>
</property>
<property path="/identity/certificateReference/x509FindType" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Cryptography.X509Certificates.X509FindType, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>FindBySubjectDistinguishedName</serializedValue>
</property>
<property path="/identity/certificateReference/findValue" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/identity/certificateReference/isChainIncluded" isComplexType="false" isExplicitlyDefined="false" clrType="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>False</serializedValue>
</property>
<property path="/name" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue>DebtRequestsAsyncPort</serializedValue>
</property>
<property path="/kind" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
<property path="/endpointConfiguration" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<serializedValue />
</property>
</properties>
</endpoint>
</endpoints>
</SavedWcfConfigurationInformation>

View File

@ -1,862 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:tns="http://dom.gosuslugi.ru/schema/integration/base/" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://dom.gosuslugi.ru/schema/integration/base/" version="13.1.10.2" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="xmldsig-core-schema.xsd" namespace="http://www.w3.org/2000/09/xmldsig#" />
<xs:simpleType name="String2000Type">
<xs:annotation>
<xs:documentation>Строка не более 2000 символов.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="2000" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="String1500Type">
<xs:annotation>
<xs:documentation>Строка не более 1500 символов.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="1500" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="String300Type">
<xs:annotation>
<xs:documentation>Строка не более 300 символов.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="300" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="String255Type">
<xs:annotation>
<xs:documentation>Скалярный тип. Строка не более 255 символов.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="255" />
<xs:minLength value="1" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="String100Type">
<xs:annotation>
<xs:documentation>Скалярный тип. Строка не более 100 символов.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="100" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="String250Type">
<xs:annotation>
<xs:documentation>Скалярный тип. Строка не более 250 символов.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="250" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="String500Type">
<xs:annotation>
<xs:documentation>Скалярный тип. Строка не более 500 символов.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="500" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="String60Type">
<xs:annotation>
<xs:documentation>Строка не более 60 символов.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="60" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LongTextType">
<xs:annotation>
<xs:documentation>Текстовое поле 2000</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="2000" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="NonEmptyStringType">
<xs:annotation>
<xs:documentation>Непустая строка</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:minLength value="1" />
<xs:pattern value=".*[^\s].*" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="BaseType">
<xs:annotation>
<xs:documentation>Базовый тип бизнес-сообщения с подписью</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element minOccurs="0" ref="ds:Signature" />
</xs:sequence>
<xs:attribute name="Id" />
</xs:complexType>
<xs:element name="RequestHeader">
<xs:annotation>
<xs:documentation>Заголовок запроса</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:complexContent mixed="false">
<xs:extension base="tns:HeaderType">
<xs:sequence>
<xs:choice>
<xs:element name="SenderID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор поставщика данных</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="orgPPAGUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор зарегистрированной организации</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Citizen">
<xs:annotation>
<xs:documentation>Информация о физическом лице</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:choice>
<xs:element name="CitizenPPAGUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор физического лица, зарегистрированного в ГИС ЖКХ </xs:documentation>
</xs:annotation>
</xs:element>
<xs:sequence>
<xs:element minOccurs="0" name="SNILS">
<xs:annotation>
<xs:documentation>СНИЛС</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="\d{11}" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element minOccurs="0" name="Document">
<xs:annotation>
<xs:documentation>Документ, удостоверяющий личность</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="DocumentType">
<xs:annotation>
<xs:documentation>Вид документа, удостоверяющего личность (НСИ №95)</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="Code">
<xs:annotation>
<xs:documentation>Код записи справочника</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="20" />
<xs:pattern value="(A{0,1}\d{1,4}(\.)?)+" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="GUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор записи в соответствующем справочнике ГИС ЖКХ</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" name="Name">
<xs:annotation>
<xs:documentation>Значение</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="tns:LongTextType">
<xs:maxLength value="1200" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="Series">
<xs:annotation>
<xs:documentation>Серия документа</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1" />
<xs:maxLength value="45" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Number">
<xs:annotation>
<xs:documentation>Номер документа</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1" />
<xs:maxLength value="45" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:choice>
<xs:element minOccurs="0" fixed="true" name="IsOperatorSignature" type="xs:boolean">
<xs:annotation>
<xs:documentation>Используется подпись Оператора ИС</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="tns:ISCreator">
<xs:annotation>
<xs:documentation>Сведения об иной ИС, с использованием которой была сформирована информация (589/944/,п.164). Только для запросов размещения информации.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="ISRequestHeader">
<xs:annotation>
<xs:documentation>Заголовок запроса</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:complexContent mixed="false">
<xs:extension base="tns:HeaderType">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="tns:ISCreator" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="ResultHeader">
<xs:annotation>
<xs:documentation>Заголовок ответа</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:complexContent mixed="false">
<xs:extension base="tns:HeaderType" />
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:complexType name="ResultType">
<xs:annotation>
<xs:documentation>Базовый тип ответа на запрос создания, редактирования, удаления </xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:choice>
<xs:element name="TransportGUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Транспортный идентификатор, определенный постащиком информации</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="UpdateGUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор объекта в ГИС ЖКХ</xs:documentation>
</xs:annotation>
</xs:element>
</xs:choice>
<xs:choice>
<xs:sequence>
<xs:element name="GUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор объекта в ГИС ЖКХ</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="UpdateDate" type="xs:dateTime">
<xs:annotation>
<xs:documentation>Дата модификации</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" name="UniqueNumber" type="xs:string">
<xs:annotation>
<xs:documentation>Уникальный номер </xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:element maxOccurs="unbounded" name="CreateOrUpdateError" type="tns:ErrorMessageType" />
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="HeaderType">
<xs:annotation>
<xs:documentation>Базовый тип заголовка</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Date" type="xs:dateTime">
<xs:annotation>
<xs:documentation>Дата отправки пакета</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="MessageGUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор сообщения</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="Attachment">
<xs:annotation>
<xs:documentation>Вложение</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="AttachmentGUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор сохраненного вложения</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="AttachmentType">
<xs:annotation>
<xs:documentation>Вложение</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Name">
<xs:annotation>
<xs:documentation>Наименование вложения</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="1024" />
<xs:minLength value="1" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Description">
<xs:annotation>
<xs:documentation>Описание вложения</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="500" />
<xs:minLength value="1" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element ref="tns:Attachment" />
<xs:element minOccurs="0" name="AttachmentHASH">
<xs:annotation>
<xs:documentation>Хэш-тег вложения по алгоритму ГОСТ в binhex.
Элемент обязателен в запросах импорта</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="AttachmentWODescriptionType">
<xs:annotation>
<xs:documentation>Вложение</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Name">
<xs:annotation>
<xs:documentation>Наименование вложения</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="1024" />
<xs:minLength value="1" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element minOccurs="0" name="Description">
<xs:annotation>
<xs:documentation>Описание вложения</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="500" />
<xs:minLength value="0" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element ref="tns:Attachment" />
<xs:element minOccurs="0" name="AttachmentHASH">
<xs:annotation>
<xs:documentation>Хэш-тег вложения по алгоритму ГОСТ в binhex</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="SignedAttachmentType">
<xs:annotation>
<xs:documentation>Базовый тип, описывающий вложение с открепленными (detached) подписями. В сервисах ГИС ЖКХ, использущих тип SignedAttachmentType, может быть наложено ограничение на максимальное количесво элементов в блоке Signature (см. контроль INT002039). </xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Attachment" type="tns:AttachmentType">
<xs:annotation>
<xs:documentation>Вложение</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element maxOccurs="unbounded" name="Signature" type="tns:AttachmentWODescriptionType">
<xs:annotation>
<xs:documentation>Открепленная (detached) подпись</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="Fault">
<xs:annotation>
<xs:documentation>Элемент Fault (для параметра Fault в операции)</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:annotation>
<xs:documentation>Базовый тип для fault-ошибки</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="ErrorCode" type="xs:string" />
<xs:element minOccurs="0" name="ErrorMessage" type="xs:string" />
<xs:element minOccurs="0" name="StackTrace" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ErrorMessage" type="tns:ErrorMessageType">
<xs:annotation>
<xs:documentation>Описание ошибок контролей или бизнес-процесса. Элемент не заполянется. Оставлен для совместимости
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:complexType name="ErrorMessageType">
<xs:annotation>
<xs:documentation>Базовый тип ошибки контроля или бизнес-процесса</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="ErrorCode" type="xs:string">
<xs:annotation>
<xs:documentation>Код ошибки</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Description" type="xs:string">
<xs:annotation>
<xs:documentation>Описание ошибки</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" name="StackTrace" type="xs:string">
<xs:annotation>
<xs:documentation>StackTrace в случае возникновения исключения</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:attribute name="version" type="xs:string">
<xs:annotation>
<xs:documentation>Версия элемента, начиная с которой поддерживается совместимость</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:element name="AckRequest">
<xs:annotation>
<xs:documentation>Возврат квитанции приема сообщения</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="Ack">
<xs:annotation>
<xs:documentation>Квитанция</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="MessageGUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор сообщения, присвоенный ГИС ЖКХ</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="RequesterMessageGUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор сообщения, присвоенный поставщиком</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getStateRequest">
<xs:annotation>
<xs:documentation>Запрос статуса отправленного сообщения</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="MessageGUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор сообщения, присвоенный ГИС ЖКХ</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getRequestsStateRequest">
<xs:annotation>
<xs:documentation>Запрос списка обработанных сообщений</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="10000" name="MessageGUIDList" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Массив идентификаторов сообщений, присвоенных ГИС ЖКХ</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getRequestsStateResult">
<xs:annotation>
<xs:documentation>Ответ на запрос списка обработанных сообщений</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:complexContent mixed="false">
<xs:extension base="tns:BaseType">
<xs:sequence>
<xs:element maxOccurs="10000" name="MessageGUIDList" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Список идентификаторов сообщений, присвоенный ГИС ЖКХ</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:complexType name="BaseAsyncResponseType">
<xs:annotation>
<xs:documentation>Базовый тип ответа на запрос статуса</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="false">
<xs:extension base="tns:BaseType">
<xs:sequence>
<xs:element name="RequestState" type="tns:AsyncRequestStateType">
<xs:annotation>
<xs:documentation>Статус обработки</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="MessageGUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор сообщения, присвоенный ГИС ЖКХ</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="CommonResultType">
<xs:annotation>
<xs:documentation>Результат выполнения C_UD</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element minOccurs="0" name="GUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор создаваемой/изменяемой сущности</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="1" name="TransportGUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Транспортный идентификатор</xs:documentation>
</xs:annotation>
</xs:element>
<xs:choice>
<xs:sequence>
<xs:annotation>
<xs:documentation>Операция выполнена успешно</xs:documentation>
</xs:annotation>
<xs:element minOccurs="0" name="UniqueNumber" type="xs:string">
<xs:annotation>
<xs:documentation>Уникальный реестровый номер</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="UpdateDate" type="xs:dateTime">
<xs:annotation>
<xs:documentation>Дата модификации</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:element maxOccurs="unbounded" name="Error">
<xs:annotation>
<xs:documentation>Описание ошибки</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:complexContent mixed="false">
<xs:extension base="tns:ErrorMessageType" />
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="AsyncRequestStateType">
<xs:annotation>
<xs:documentation>Статус обработки сообщения в асинхронном обмене (1- получено; 2 - в обработке; 3- обработано)</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:byte">
<xs:enumeration value="1" />
<xs:enumeration value="2" />
<xs:enumeration value="3" />
</xs:restriction>
</xs:simpleType>
<xs:element name="TransportGUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Транспортный идентификатор</xs:documentation>
</xs:annotation>
</xs:element>
<xs:simpleType name="GUIDType">
<xs:annotation>
<xs:documentation>GUID-тип.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}" />
</xs:restriction>
</xs:simpleType>
<xs:element name="ModificationDate" type="xs:dateTime">
<xs:annotation>
<xs:documentation>Дата модификации объекта</xs:documentation>
</xs:annotation>
</xs:element>
<xs:simpleType name="YearType">
<xs:annotation>
<xs:documentation>Тип, описывающий год</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:short">
<xs:minInclusive value="1600" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="MonthType">
<xs:annotation>
<xs:documentation>Тип, описывающий месяц</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:int">
<xs:maxInclusive value="12" />
<xs:minInclusive value="1" />
</xs:restriction>
</xs:simpleType>
<xs:element name="Month" type="tns:MonthType">
<xs:annotation>
<xs:documentation>Месяц</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Year">
<xs:annotation>
<xs:documentation>Год</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:short">
<xs:minInclusive value="1920" />
<xs:maxInclusive value="2050" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:complexType name="YearMonth">
<xs:annotation>
<xs:documentation>Определенный месяц определенного года</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element ref="tns:Year" />
<xs:element ref="tns:Month" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Period">
<xs:annotation>
<xs:documentation>Временной период (обе даты обязательны)</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="startDate" type="xs:date">
<xs:annotation>
<xs:documentation>Начало периода</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="endDate" type="xs:date">
<xs:annotation>
<xs:documentation>Конец периода</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PeriodOpen">
<xs:annotation>
<xs:documentation>Открытый временной период (даты необязательны)</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element minOccurs="0" name="startDate" type="xs:date">
<xs:annotation>
<xs:documentation>Начало периода</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" name="endDate" type="xs:date">
<xs:annotation>
<xs:documentation>Конец периода</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="VolumeType">
<xs:annotation>
<xs:documentation>Тип объема</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:decimal">
<xs:fractionDigits value="3" />
<xs:minInclusive value="0" />
<xs:totalDigits value="11" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="RegionType">
<xs:annotation>
<xs:documentation>Ссылка на субъект РФ (ФИАС)</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="code">
<xs:annotation>
<xs:documentation>Код региона (ФИАС)</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:length value="2" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element minOccurs="0" name="name">
<xs:annotation>
<xs:documentation>Полное наименование</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="500" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="OKTMORefType">
<xs:annotation>
<xs:documentation>Ссылка на ОКТМО</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="code">
<xs:annotation>
<xs:documentation>Код по ОКТМО</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="11" />
<xs:pattern value="\d{11}|\d{8}" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element minOccurs="0" name="name">
<xs:annotation>
<xs:documentation>Полное наименование</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="500" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="OKEIType">
<xs:restriction base="xs:string">
<xs:pattern value="A{0,1}\d{3,4}" />
</xs:restriction>
</xs:simpleType>
<xs:element name="OKEI" type="tns:OKEIType">
<xs:annotation>
<xs:documentation>Код ОКЕИ</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="orgPPAGUID" type="tns:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор зарегистрированной организации</xs:documentation>
</xs:annotation>
</xs:element>
<xs:complexType name="DocumentPortalType">
<xs:annotation>
<xs:documentation>Базовый тип документа ОЧ</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Name">
<xs:annotation>
<xs:documentation>Наименование документа</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1" />
<xs:maxLength value="500" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element minOccurs="0" name="DocNumber">
<xs:annotation>
<xs:documentation>Номер документа</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1" />
<xs:maxLength value="500" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="ApproveDate" type="xs:date">
<xs:annotation>
<xs:documentation>Дата принятия документа органом власти</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Attachment" type="tns:AttachmentType">
<xs:annotation>
<xs:documentation>Вложение</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="ISCreator">
<xs:annotation>
<xs:documentation>Сведения об иной ИС, с использованием которой была сформирована информация (589/944/,п.164)</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="ISName" type="tns:String255Type">
<xs:annotation>
<xs:documentation>Наименование ИС</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="ISOperatorName" type="tns:String255Type">
<xs:annotation>
<xs:documentation>Наименование Оператора ИС</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="OKTMOType">
<xs:annotation>
<xs:documentation>Код по ОКТМО</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="11" />
<xs:pattern value="\d{11}|\d{8}" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="OKTMOImportType">
<xs:annotation>
<xs:documentation>Код по ОКТМО</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="8" />
<xs:pattern value="\d{8}" />
</xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@ -1,163 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:base="http://dom.gosuslugi.ru/schema/integration/base/" xmlns:ns="http://www.w3.org/2000/09/xmldsig#" xmlns:drs="http://dom.gosuslugi.ru/schema/integration/drs/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://dom.gosuslugi.ru/schema/integration/nsi-base/" xmlns:tns="http://dom.gosuslugi.ru/schema/integration/drs-service-async" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://dom.gosuslugi.ru/schema/integration/drs-service-async" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualified" version="13.1.2.6">
<xs:import schemaLocation="hcs-debt-requests-types.xsd" namespace="http://dom.gosuslugi.ru/schema/integration/drs/" />
<xs:import schemaLocation="../lib/hcs-base.xsd" namespace="http://dom.gosuslugi.ru/schema/integration/base/" />
</xs:schema>
</wsdl:types>
<wsdl:message name="RequestHeader">
<wsdl:part name="Header" element="base:RequestHeader" />
</wsdl:message>
<wsdl:message name="ResultHeader">
<wsdl:part name="Header" element="base:ResultHeader" />
</wsdl:message>
<wsdl:message name="importDRsRequest">
<wsdl:part name="importDRsRequest" element="drs:importDRsRequest" />
</wsdl:message>
<wsdl:message name="importDRsResult">
<wsdl:part name="importDRsResult" element="base:AckRequest" />
</wsdl:message>
<wsdl:message name="exportDRsRequest">
<wsdl:part name="exportDRsRequest" element="drs:exportDRsRequest" />
</wsdl:message>
<wsdl:message name="exportDRsResult">
<wsdl:part name="exportDRsResult" element="base:AckRequest" />
</wsdl:message>
<wsdl:message name="importDSRsRequest">
<wsdl:part name="importDSRsRequest" element="drs:importDSRResponsesRequest" />
</wsdl:message>
<wsdl:message name="importDSRsResult">
<wsdl:part name="importDSRsResult" element="base:AckRequest" />
</wsdl:message>
<wsdl:message name="exportDSRsRequest">
<wsdl:part name="exportDSRsRequest" element="drs:exportDSRsRequest" />
</wsdl:message>
<wsdl:message name="exportDSRsResult">
<wsdl:part name="exportDSRsResult" element="base:AckRequest" />
</wsdl:message>
<wsdl:message name="getStateRequest">
<wsdl:part name="getStateRequest" element="base:getStateRequest" />
</wsdl:message>
<wsdl:message name="getStateResult">
<wsdl:part name="getStateResult" element="drs:getStateResult" />
</wsdl:message>
<wsdl:message name="Fault">
<wsdl:part name="Fault" element="base:Fault" />
</wsdl:message>
<wsdl:portType name="DebtRequestsAsyncPort">
<wsdl:operation name="importDebtRequests">
<wsdl:documentation>Загрузка в ГИС ЖКХ запросов о наличии задолженности за ЖКУ (организациями, направляющими запросы)</wsdl:documentation>
<wsdl:input message="tns:importDRsRequest" />
<wsdl:output message="tns:importDRsResult" />
<wsdl:fault name="InvalidRequest" message="tns:Fault" />
</wsdl:operation>
<wsdl:operation name="exportDebtSubrequests">
<wsdl:documentation>Выгрузка из ГИС ЖКХ подзапросов о наличии задолженности за ЖКУ (организациями, предоставляющими ЖКУ)</wsdl:documentation>
<wsdl:input message="tns:exportDSRsRequest" />
<wsdl:output message="tns:exportDSRsResult" />
<wsdl:fault name="InvalidRequest" message="tns:Fault" />
</wsdl:operation>
<wsdl:operation name="importResponses">
<wsdl:documentation>Загрузка в ГИС ЖКХ ответов на запросы о наличии задолженности за ЖКУ (организациями, предоставляющими ЖКУ)</wsdl:documentation>
<wsdl:input message="tns:importDSRsRequest" />
<wsdl:output message="tns:importDSRsResult" />
<wsdl:fault name="InvalidRequest" message="tns:Fault" />
</wsdl:operation>
<wsdl:operation name="exportDebtRequests">
<wsdl:documentation>Выгрузка из ГИС ЖКХ запросов о наличии задолженности за ЖКУ (организациями, направляющими запросы)</wsdl:documentation>
<wsdl:input message="tns:exportDRsRequest" />
<wsdl:output message="tns:exportDRsResult" />
<wsdl:fault name="InvalidRequest" message="tns:Fault" />
</wsdl:operation>
<wsdl:operation name="getState">
<wsdl:documentation>Результат обработки асинхронного вызова</wsdl:documentation>
<wsdl:input message="tns:getStateRequest" />
<wsdl:output message="tns:getStateResult" />
<wsdl:fault name="InvalidRequest" message="tns:Fault" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="DebtRequestsAsyncBinding" type="tns:DebtRequestsAsyncPort">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="importDebtRequests">
<wsdl:documentation>Загрузка в ГИС ЖКХ запросов о наличии задолженности за ЖКУ (организациями, направляющими запросы)</wsdl:documentation>
<soap:operation soapAction="urn:importDebtRequests" />
<wsdl:input>
<soap:body use="literal" />
<soap:header message="tns:RequestHeader" part="Header" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
<soap:header message="tns:ResultHeader" part="Header" use="literal" />
</wsdl:output>
<wsdl:fault name="InvalidRequest">
<soap:fault use="literal" name="InvalidRequest" namespace="" />
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="exportDebtSubrequests">
<wsdl:documentation>Выгрузка из ГИС ЖКХ подзапросов о наличии задолженности за ЖКУ (организациями, предоставляющими ЖКУ)</wsdl:documentation>
<soap:operation soapAction="urn:exportDebtSubrequests" />
<wsdl:input>
<soap:body use="literal" />
<soap:header message="tns:RequestHeader" part="Header" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
<soap:header message="tns:ResultHeader" part="Header" use="literal" />
</wsdl:output>
<wsdl:fault name="InvalidRequest">
<soap:fault use="literal" name="InvalidRequest" namespace="" />
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="importResponses">
<wsdl:documentation>Загрузка в ГИС ЖКХ ответов на запросы о наличии задолженности за ЖКУ (организациями, предоставляющими ЖКУ)</wsdl:documentation>
<soap:operation soapAction="urn:importResponses" />
<wsdl:input>
<soap:body use="literal" />
<soap:header message="tns:RequestHeader" part="Header" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
<soap:header message="tns:ResultHeader" part="Header" use="literal" />
</wsdl:output>
<wsdl:fault name="InvalidRequest">
<soap:fault use="literal" name="InvalidRequest" namespace="" />
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="exportDebtRequests">
<wsdl:documentation>Выгрузка из ГИС ЖКХ запросов о наличии задолженности за ЖКУ (организациями, направляющими запросы)</wsdl:documentation>
<soap:operation soapAction="urn:exportDebtRequests" />
<wsdl:input>
<soap:body use="literal" />
<soap:header message="tns:RequestHeader" part="Header" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
<soap:header message="tns:ResultHeader" part="Header" use="literal" />
</wsdl:output>
<wsdl:fault name="InvalidRequest">
<soap:fault use="literal" name="InvalidRequest" namespace="" />
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="getState">
<soap:operation soapAction="urn:getState" />
<wsdl:input>
<soap:body use="literal" />
<soap:header message="tns:RequestHeader" part="Header" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
<soap:header message="tns:ResultHeader" part="Header" use="literal" />
</wsdl:output>
<wsdl:fault name="InvalidRequest">
<soap:fault use="literal" name="InvalidRequest" namespace="" />
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="DebtRequestsServiceAsync">
<wsdl:documentation>Сервис управления запросами о наличии задолженности за ЖКУ</wsdl:documentation>
<wsdl:port name="DebtRequestsAsyncPort" binding="tns:DebtRequestsAsyncBinding">
<soap:address location="https://api.dom.gosuslugi.ru/ext-bus-debtreq-service/services/DebtRequestsAsync" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@ -1,427 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:base="http://dom.gosuslugi.ru/schema/integration/base/" xmlns:tns="http://dom.gosuslugi.ru/schema/integration/nsi-base/" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://dom.gosuslugi.ru/schema/integration/nsi-base/" version="11.2.1.1" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="hcs-base.xsd" namespace="http://dom.gosuslugi.ru/schema/integration/base/" />
<xs:simpleType name="nsiCodeType">
<xs:restriction base="xs:string">
<xs:maxLength value="20" />
<xs:pattern value="(A{0,1}\d{1,4}(\.)?)+" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="nsiRef">
<xs:annotation>
<xs:documentation>Ссылка на справочник</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Code" type="tns:nsiCodeType">
<xs:annotation>
<xs:documentation>Код записи справочника</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="GUID" type="base:GUIDType">
<xs:annotation>
<xs:documentation>Идентификатор записи в соответствующем справочнике ГИС ЖКХ</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" name="Name">
<xs:annotation>
<xs:documentation>Значение</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="base:LongTextType">
<xs:maxLength value="1200" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="NsiItemNameType">
<xs:annotation>
<xs:documentation>Скалярный тип. Наименование справочника. Строка не более 200 символов.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="2500" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="NsiItemRegistryNumberType">
<xs:annotation>
<xs:documentation>Скалярный тип. Реестровый номер справочника. Код не более 10 символов.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:positiveInteger">
<xs:totalDigits value="10" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="NsiItemInfoType">
<xs:annotation>
<xs:documentation>Составной тип. Наименование, дата и время последнего изменения справочника.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="RegistryNumber" type="tns:NsiItemRegistryNumberType">
<xs:annotation>
<xs:documentation>Реестровый номер справочника.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Name" type="tns:NsiItemNameType">
<xs:annotation>
<xs:documentation>Наименование справочника.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Modified" type="xs:dateTime">
<xs:annotation>
<xs:documentation>Дата и время последнего изменения справочника.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="NsiListType">
<xs:annotation>
<xs:documentation>Перечень справочников с датой последнего изменения каждого из них.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Created" type="xs:dateTime">
<xs:annotation>
<xs:documentation>Дата и время формирования перечня справочников.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element maxOccurs="unbounded" name="NsiItemInfo" type="tns:NsiItemInfoType">
<xs:annotation>
<xs:documentation>Наименование, дата и время последнего изменения справочника.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element ref="tns:ListGroup" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="NsiItemType">
<xs:annotation>
<xs:documentation>Данные справочника.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="NsiItemRegistryNumber" type="tns:NsiItemRegistryNumberType">
<xs:annotation>
<xs:documentation>Реестровый номер справочника.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Created" type="xs:dateTime">
<xs:annotation>
<xs:documentation>Дата и время формирования данных справочника.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element maxOccurs="unbounded" name="NsiElement" type="tns:NsiElementType">
<xs:annotation>
<xs:documentation>Элемент справочника верхнего уровня.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="NsiElementType">
<xs:annotation>
<xs:documentation>Составной тип. Элемент справочника.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Code" type="tns:nsiCodeType">
<xs:annotation>
<xs:documentation>Код элемента справочника, уникальный в пределах справочника.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="GUID" type="base:GUIDType">
<xs:annotation>
<xs:documentation>Глобально-уникальный идентификатор элемента справочника.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:choice>
<xs:element name="Modified" type="xs:dateTime">
<xs:annotation>
<xs:documentation>Дата и время последнего изменения элемента справочника (в том числе создания).</xs:documentation>
</xs:annotation>
</xs:element>
<xs:sequence>
<xs:element name="StartDate" type="xs:dateTime">
<xs:annotation>
<xs:documentation>Дата начала действия значения</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="EndDate" type="xs:dateTime">
<xs:annotation>
<xs:documentation>Дата окончания действия значения</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:choice>
<xs:element name="IsActual" type="xs:boolean">
<xs:annotation>
<xs:documentation>Признак актуальности элемента справочника.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="unbounded" name="NsiElementField" type="tns:NsiElementFieldType">
<xs:annotation>
<xs:documentation>Наименование и значение поля для элемента справочника.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="unbounded" name="ChildElement" type="tns:NsiElementType">
<xs:annotation>
<xs:documentation>Дочерний элемент.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="NsiElementFieldType" abstract="true">
<xs:annotation>
<xs:documentation>Составной тип. Наименование и значение поля для элемента справочника. Абстрактный тип.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Name" type="tns:FieldNameType">
<xs:annotation>
<xs:documentation>Наименование поля элемента справочника.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="NsiElementStringFieldType">
<xs:annotation>
<xs:documentation>Составной тип. Наименование и значение поля типа "Строка" для элемента справочника.</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="false">
<xs:extension base="tns:NsiElementFieldType">
<xs:sequence>
<xs:element minOccurs="0" name="Value" type="xs:string">
<xs:annotation>
<xs:documentation>Значение поля элемента справочника типа "Строка".</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="NsiElementBooleanFieldType">
<xs:annotation>
<xs:documentation>Составной тип. Наименование и значение поля типа "Да/Нет" для элемента справочника.</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="false">
<xs:extension base="tns:NsiElementFieldType">
<xs:sequence>
<xs:element minOccurs="0" name="Value" type="xs:boolean">
<xs:annotation>
<xs:documentation>Значение поля элемента справочника типа "Да/Нет".</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="NsiElementFloatFieldType">
<xs:annotation>
<xs:documentation>Составной тип. Наименование и значение поля типа "Вещественное" для элемента справочника.</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="false">
<xs:extension base="tns:NsiElementFieldType">
<xs:sequence>
<xs:element minOccurs="0" name="Value" type="xs:float">
<xs:annotation>
<xs:documentation>Значение поля элемента справочника типа "Вещественное".</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="NsiElementDateFieldType">
<xs:annotation>
<xs:documentation>Составной тип. Наименование и значение поля типа "Дата" для элемента справочника.</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="false">
<xs:extension base="tns:NsiElementFieldType">
<xs:sequence>
<xs:element minOccurs="0" name="Value" type="xs:date">
<xs:annotation>
<xs:documentation>Значение поля элемента справочника типа "Дата".</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="NsiElementIntegerFieldType">
<xs:annotation>
<xs:documentation>Составной тип. Наименование и значение поля типа "Целое число" для элемента справочника.</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="false">
<xs:extension base="tns:NsiElementFieldType">
<xs:sequence>
<xs:element minOccurs="0" name="Value" type="xs:integer">
<xs:annotation>
<xs:documentation>Значение поля элемента справочника типа "Целое число".</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="NsiElementEnumFieldType">
<xs:annotation>
<xs:documentation>Составной тип. Наименование и значение поля типа "Перечислимый" для элемента справочника.</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="false">
<xs:extension base="tns:NsiElementFieldType">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Position">
<xs:annotation>
<xs:documentation>Запись элемента справочника типа "Перечислимый".</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="GUID">
<xs:annotation>
<xs:documentation>Код поля элемента справочника типа "Перечислимый".</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Value" type="xs:string">
<xs:annotation>
<xs:documentation>Значение поля элемента справочника типа "Перечислимый".</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="NsiElementNsiFieldType">
<xs:annotation>
<xs:documentation>Составной тип. Наименование и значение поля типа "Ссылка на справочник" для элемента справочника.</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="false">
<xs:extension base="tns:NsiElementFieldType">
<xs:sequence>
<xs:element minOccurs="0" name="NsiRef">
<xs:annotation>
<xs:documentation>Ссылка на справочник.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="NsiItemRegistryNumber" type="tns:NsiItemRegistryNumberType">
<xs:annotation>
<xs:documentation>Реестровый номер справочника.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element ref="tns:ListGroup" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="NsiElementNsiRefFieldType">
<xs:annotation>
<xs:documentation>Составной тип. Наименование и значение поля типа "Ссылка на элемент внутреннего справочника" для элемента справочника.</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="false">
<xs:extension base="tns:NsiElementFieldType">
<xs:sequence>
<xs:element minOccurs="0" name="NsiRef">
<xs:annotation>
<xs:documentation>Ссылка на элемент внутреннего справочника.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="NsiItemRegistryNumber" type="tns:NsiItemRegistryNumberType">
<xs:annotation>
<xs:documentation>Реестровый номер справочника.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Ref" type="tns:nsiRef">
<xs:annotation>
<xs:documentation>Ссылка на элемент справочника.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="NsiElementOkeiRefFieldType">
<xs:annotation>
<xs:documentation>Составной тип. Наименование и значение поля типа "Ссылка на элемент справочника ОКЕИ" для элемента справочника.</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="false">
<xs:extension base="tns:NsiElementFieldType">
<xs:sequence>
<xs:element minOccurs="0" name="Code" type="tns:nsiCodeType">
<xs:annotation>
<xs:documentation>Код единицы измерения по справочнику ОКЕИ.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="NsiElementFiasAddressRefFieldType">
<xs:annotation>
<xs:documentation>Составной тип. Наименование и значение поля типа "Ссылка на элемент справочника ФИАС" для элемента справочника.</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="false">
<xs:extension base="tns:NsiElementFieldType">
<xs:sequence>
<xs:element minOccurs="0" name="NsiRef">
<xs:annotation>
<xs:documentation>Ссылка на элемент справочника ФИАС.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="Guid" type="xs:string">
<xs:annotation>
<xs:documentation>Идентификационный код позиции в справочнике ФИАС.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="aoGuid" type="xs:string">
<xs:annotation>
<xs:documentation>Глобально-уникальный идентификатор адресного объекта в справочнике ФИАС.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="NsiElementAttachmentFieldType">
<xs:annotation>
<xs:documentation>Составной тип. Наименование и значение поля "Вложение"</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="false">
<xs:extension base="tns:NsiElementFieldType">
<xs:sequence>
<xs:element name="Document" type="base:AttachmentType">
<xs:annotation>
<xs:documentation>Документ</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:simpleType name="FieldNameType">
<xs:annotation>
<xs:documentation>Скалярный тип. Наименование поля элемента справочника. Строка не более 200 символов.</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:maxLength value="200" />
</xs:restriction>
</xs:simpleType>
<xs:element name="ListGroup">
<xs:annotation>
<xs:documentation>Группа справочника:
NSI - (по умолчанию) общесистемный
NSIRAO - ОЖФ</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="NSI" />
<xs:enumeration value="NSIRAO" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:schema>

View File

@ -1,213 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<schema xmlns:ds="http://www.w3.org/2000/09/xmldsig#" elementFormDefault="qualified" targetNamespace="http://www.w3.org/2000/09/xmldsig#" version="0.1" xmlns="http://www.w3.org/2001/XMLSchema">
<simpleType name="CryptoBinary">
<restriction base="base64Binary" />
</simpleType>
<element name="Signature" type="ds:SignatureType" />
<complexType name="SignatureType">
<sequence>
<element ref="ds:SignedInfo" />
<element ref="ds:SignatureValue" />
<element minOccurs="0" ref="ds:KeyInfo" />
<element minOccurs="0" maxOccurs="unbounded" ref="ds:Object" />
</sequence>
<attribute name="Id" type="ID" use="optional" />
</complexType>
<element name="SignatureValue" type="ds:SignatureValueType" />
<complexType name="SignatureValueType">
<simpleContent>
<extension base="base64Binary">
<attribute name="Id" type="ID" use="optional" />
</extension>
</simpleContent>
</complexType>
<element name="SignedInfo" type="ds:SignedInfoType" />
<complexType name="SignedInfoType">
<sequence>
<element ref="ds:CanonicalizationMethod" />
<element ref="ds:SignatureMethod" />
<element maxOccurs="unbounded" ref="ds:Reference" />
</sequence>
<attribute name="Id" type="ID" use="optional" />
</complexType>
<element name="CanonicalizationMethod" type="ds:CanonicalizationMethodType" />
<complexType name="CanonicalizationMethodType" mixed="true">
<sequence>
<any minOccurs="0" maxOccurs="unbounded" namespace="##any" />
</sequence>
<attribute name="Algorithm" type="anyURI" use="required" />
</complexType>
<element name="SignatureMethod" type="ds:SignatureMethodType" />
<complexType name="SignatureMethodType" mixed="true">
<sequence>
<element minOccurs="0" name="HMACOutputLength" type="ds:HMACOutputLengthType" />
<any minOccurs="0" maxOccurs="unbounded" namespace="##other" />
</sequence>
<attribute name="Algorithm" type="anyURI" use="required" />
</complexType>
<element name="Reference" type="ds:ReferenceType" />
<complexType name="ReferenceType">
<sequence>
<element minOccurs="0" ref="ds:Transforms" />
<element ref="ds:DigestMethod" />
<element ref="ds:DigestValue" />
</sequence>
<attribute name="Id" type="ID" use="optional" />
<attribute name="URI" type="anyURI" use="optional" />
<attribute name="Type" type="anyURI" use="optional" />
</complexType>
<element name="Transforms" type="ds:TransformsType" />
<complexType name="TransformsType">
<sequence>
<element maxOccurs="unbounded" ref="ds:Transform" />
</sequence>
</complexType>
<element name="Transform" type="ds:TransformType" />
<complexType name="TransformType" mixed="true">
<choice minOccurs="0" maxOccurs="unbounded">
<any namespace="##other" processContents="lax" />
<element name="XPath" type="string" />
</choice>
<attribute name="Algorithm" type="anyURI" use="required" />
</complexType>
<element name="DigestMethod" type="ds:DigestMethodType" />
<complexType name="DigestMethodType" mixed="true">
<sequence>
<any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax" />
</sequence>
<attribute name="Algorithm" type="anyURI" use="required" />
</complexType>
<element name="DigestValue" type="ds:DigestValueType" />
<simpleType name="DigestValueType">
<restriction base="base64Binary" />
</simpleType>
<element name="KeyInfo" type="ds:KeyInfoType" />
<complexType name="KeyInfoType" mixed="true">
<choice maxOccurs="unbounded">
<element ref="ds:KeyName" />
<element ref="ds:KeyValue" />
<element ref="ds:RetrievalMethod" />
<element ref="ds:X509Data" />
<element ref="ds:PGPData" />
<element ref="ds:SPKIData" />
<element ref="ds:MgmtData" />
<any namespace="##other" processContents="lax" />
</choice>
<attribute name="Id" type="ID" use="optional" />
</complexType>
<element name="KeyName" type="string" />
<element name="MgmtData" type="string" />
<element name="KeyValue" type="ds:KeyValueType" />
<complexType name="KeyValueType" mixed="true">
<choice>
<element ref="ds:DSAKeyValue" />
<element ref="ds:RSAKeyValue" />
<any namespace="##other" processContents="lax" />
</choice>
</complexType>
<element name="RetrievalMethod" type="ds:RetrievalMethodType" />
<complexType name="RetrievalMethodType">
<sequence>
<element minOccurs="0" ref="ds:Transforms" />
</sequence>
<attribute name="URI" type="anyURI" />
<attribute name="Type" type="anyURI" use="optional" />
</complexType>
<element name="X509Data" type="ds:X509DataType" />
<complexType name="X509DataType">
<sequence maxOccurs="unbounded">
<choice>
<element name="X509IssuerSerial" type="ds:X509IssuerSerialType" />
<element name="X509SKI" type="base64Binary" />
<element name="X509SubjectName" type="string" />
<element name="X509Certificate" type="base64Binary" />
<element name="X509CRL" type="base64Binary" />
<any namespace="##other" processContents="lax" />
</choice>
</sequence>
</complexType>
<complexType name="X509IssuerSerialType">
<sequence>
<element name="X509IssuerName" type="string" />
<element name="X509SerialNumber" type="integer" />
</sequence>
</complexType>
<element name="PGPData" type="ds:PGPDataType" />
<complexType name="PGPDataType">
<choice>
<sequence>
<element name="PGPKeyID" type="base64Binary" />
<element minOccurs="0" name="PGPKeyPacket" type="base64Binary" />
<any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax" />
</sequence>
<sequence>
<element name="PGPKeyPacket" type="base64Binary" />
<any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax" />
</sequence>
</choice>
</complexType>
<element name="SPKIData" type="ds:SPKIDataType" />
<complexType name="SPKIDataType">
<sequence maxOccurs="unbounded">
<element name="SPKISexp" type="base64Binary" />
<any minOccurs="0" namespace="##other" processContents="lax" />
</sequence>
</complexType>
<element name="Object" type="ds:ObjectType" />
<complexType name="ObjectType" mixed="true">
<sequence minOccurs="0" maxOccurs="unbounded">
<any namespace="##any" processContents="lax" />
</sequence>
<attribute name="Id" type="ID" use="optional" />
<attribute name="MimeType" type="string" use="optional" />
<attribute name="Encoding" type="anyURI" use="optional" />
</complexType>
<element name="Manifest" type="ds:ManifestType" />
<complexType name="ManifestType">
<sequence>
<element maxOccurs="unbounded" ref="ds:Reference" />
</sequence>
<attribute name="Id" type="ID" use="optional" />
</complexType>
<element name="SignatureProperties" type="ds:SignaturePropertiesType" />
<complexType name="SignaturePropertiesType">
<sequence>
<element maxOccurs="unbounded" ref="ds:SignatureProperty" />
</sequence>
<attribute name="Id" type="ID" use="optional" />
</complexType>
<element name="SignatureProperty" type="ds:SignaturePropertyType" />
<complexType name="SignaturePropertyType" mixed="true">
<choice maxOccurs="unbounded">
<any namespace="##other" processContents="lax" />
</choice>
<attribute name="Target" type="anyURI" use="required" />
<attribute name="Id" type="ID" use="optional" />
</complexType>
<simpleType name="HMACOutputLengthType">
<restriction base="integer" />
</simpleType>
<element name="DSAKeyValue" type="ds:DSAKeyValueType" />
<complexType name="DSAKeyValueType">
<sequence>
<sequence minOccurs="0">
<element name="P" type="ds:CryptoBinary" />
<element name="Q" type="ds:CryptoBinary" />
</sequence>
<element minOccurs="0" name="G" type="ds:CryptoBinary" />
<element name="Y" type="ds:CryptoBinary" />
<element minOccurs="0" name="J" type="ds:CryptoBinary" />
<sequence minOccurs="0">
<element name="Seed" type="ds:CryptoBinary" />
<element name="PgenCounter" type="ds:CryptoBinary" />
</sequence>
</sequence>
</complexType>
<element name="RSAKeyValue" type="ds:RSAKeyValueType" />
<complexType name="RSAKeyValueType">
<sequence>
<element name="Modulus" type="ds:CryptoBinary" />
<element name="Exponent" type="ds:CryptoBinary" />
</sequence>
</complexType>
</schema>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="AckRequest" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>Hcs.Service.Async.DeviceMetering.v15_7_0_1.AckRequest, Connected Services.Service.Async.DeviceMetering.v15_7_0_1.Reference.cs.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="ResultHeader" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>Hcs.Service.Async.DeviceMetering.v15_7_0_1.ResultHeader, Connected Services.Service.Async.DeviceMetering.v15_7_0_1.Reference.cs.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

Some files were not shown because too many files have changed in this diff Show More