feat: внешняя обработка «Просмотр реестров платежей» 1.0.0 — чтение XML-реестров к платёжным поручениям и печать реестра

This commit is contained in:
15 changed files with 2462 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
# Служебные файлы EDT и ОС
.metadata/
*.log
*.bak
*.tmp
Thumbs.db
.DS_Store
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ПросмотрРеестровПлатежей</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
<nature>com._1c.g5.v8.dt.core.V8ExternalObjectsNature</nature>
</natures>
</projectDescription>
+8
View File
@@ -0,0 +1,8 @@
{
"version": 1,
"settings": {
"common-module-server-call": {
"enabled": true
}
}
}
@@ -0,0 +1,2 @@
com._1c.g5.v8.dt.platform.services.core.PREF_AUTO_EXT_OBJECT_DUMP_GENERATION=true
eclipse.preferences.version=1
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
topObjects=true
+3
View File
@@ -0,0 +1,3 @@
addModuleStrictTypesAnnotation=false
createModuleStructure=false
eclipse.preferences.version=1
+3
View File
@@ -0,0 +1,3 @@
commonChecks=true
eclipse.preferences.version=1
standardChecks=true
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8
+4
View File
@@ -0,0 +1,4 @@
Manifest-Version: 1.0
Runtime-Version: 8.5.1
X-External-Script-Variant: Russian
X-External-Languages: ru;name="Русский"
+67
View File
@@ -0,0 +1,67 @@
# Просмотр реестров платежей
Внешняя обработка 1С:Предприятия для просмотра и печати XML-файлов реестров к платёжным поручениям на общую сумму с реестром (формат `ProcessRegPayOrder`, поставка форматов `PPRegister`, вид обмена «Обмен с ОФК (ПП с реестром)»).
Обработка внешняя: конфигурацию не меняет, с поддержки не снимает, ставится как файл `.epf`.
## Зачем
Организации получают из СУФД файлы реестров, в которых перечислены распоряжения плательщиков. Читать XML неудобно, а грузить кассовые поступления и разбирать назначения платежей ради просмотра — избыточно. Обработка показывает содержимое файлов в таблице и печатает реестр.
## Возможности
- выбор каталога с файлами `*.xml` — кнопкой «Выбрать каталог» или в поле каталога;
- обработка всех файлов каталога за один проход, строки всех реестров в одной таблице;
- контроль целостности: сумма строк сверяется с суммой платёжного поручения из файла, расхождение выводится предупреждением;
- мягкая обработка ошибок: файл, который не удалось прочитать, пропускается, остальные обрабатываются;
- печать: заголовок «Реестр платежей», таблица с рамками и строка «ИТОГО» по сумме.
## Колонки
| Колонка | Источник в XML |
|---|---|
| Файл | имя файла |
| № ПП | `NOM_PP` |
| № распоряжения | `NOM_PAY_DOC` |
| Дата распоряжения | `DATE_PAY_DOC`, при пустом — `DATE_REESTR_PP` |
| Плательщик | `NAME_PLAT` до разделителя `//`, при пустом — `FIO_PLAT` |
| Счёт плательщика | `NOM_LS_PLAT` |
| Сумма | `SUM_REESTR_PP` (в файле в копейках, выводится в рублях) |
| Назначение платежа | `PURPOSE` целиком |
| Статус | `PAYSTATUS` |
## Требования
- платформа 1С:Предприятие 8.5.1 (под ней собран проект);
- любая конфигурация — обработка внешняя, объекты конфигурации не используются;
- файлы реестров в формате `ProcessRegPayOrder`.
## Как запустить
1. `1С:Предприятие` → **Файл → Открыть…** → `bin/ПросмотрРеестровПлатежей.epf`.
2. Нажать «Выбрать каталог» и указать папку с файлами реестров.
3. Нажать «Сформировать» — строки появятся в таблице.
4. Нажать «Печать реестра» — сформируется печатная форма.
## Как открыть и собрать в EDT
1. **File → Import → General → Existing Projects into Workspace**, выбрать корневую папку репозитория. Проект называется `ПросмотрРеестровПлатежей`.
2. Сборка: **Проект → Очистить**, затем **Проект → Собрать**. Результат — `bin/ПросмотрРеестровПлатежей.epf`. Отдельного экспорта `.epf` в EDT не требуется.
## Устройство
Вся логика — в модуле формы обработки (`src/ExternalDataProcessors/ПросмотрРеестровПлатежей/Forms/Форма/Module.bsl`); модуль объекта не используется.
- клиентские обработчики: выбор каталога, «Сформировать», «Печать реестра»;
- серверные (`&НаСервере` / `&НаСервереБезКонтекста`): чтение каталога (`НайтиФайлы`), разбор XML потоком (`ЧтениеXML`), заполнение таблицы формы, формирование табличного документа;
- суммы из файла приходят в копейках и делятся на 100; даты разбираются из формата `ГГГГ-ММ-ДД`.
## Ограничения
- назначение платежа выводится целиком и не разбирается на реквизиты (лицевой счёт ребёнка, группа, период): у разных организаций свободный текст, разбор по запятым даёт мусор;
- электронная подпись файлов не проверяется: подписанные контейнеры нужно предварительно расшифровать;
- обрабатываются только файлы формата «платёжное поручение на общую сумму с реестром»; прочие файлы пропускаются с сообщением.
## Версия
1.0.0
@@ -0,0 +1,686 @@
#Область ОбработчикиСобытийЭлементовШапкиФормы
&НаКлиенте
Процедура КаталогНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ВыбратьКаталогИзДиалога();
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиКомандФормы
&НаКлиенте
Процедура ВыбратьКаталог(Команда)
ВыбратьКаталогИзДиалога();
КонецПроцедуры
&НаКлиенте
Процедура Сформировать(Команда)
Если Не ЗначениеЗаполнено(Каталог) Тогда
ПоказатьПредупреждение(, НСтр("ru = 'Укажите каталог с файлами реестров.'"));
Возврат;
КонецЕсли;
Результат = ПрочитатьРеестры();
Если ЗначениеЗаполнено(Результат.ТекстСообщений) Тогда
ПоказатьПредупреждение(, Результат.ТекстСообщений);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура Печать(Команда)
Если ТаблицаРеестра.Количество() = 0 Тогда
ПоказатьПредупреждение(, НСтр("ru = 'Список строк пуст. Укажите каталог и нажмите «Сформировать».'"));
Возврат;
КонецЕсли;
ТабличныйДокумент = СформироватьПечатнуюФорму();
ТабличныйДокумент.Показать(НСтр("ru = 'Реестр платежей'"));
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
&НаКлиенте
Процедура ВыбратьКаталогИзДиалога()
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
Диалог.Заголовок = НСтр("ru = 'Каталог с файлами реестров'");
Если ЗначениеЗаполнено(Каталог) Тогда
Диалог.Каталог = Каталог;
КонецЕсли;
Если Диалог.Выбрать() Тогда
Каталог = Диалог.Каталог;
КонецЕсли;
КонецПроцедуры
// Читает все xml-файлы реестров из каталога и заполняет таблицу формы.
//
// Возвращаемое значение:
// Структура - ТекстСообщений - Строка - сообщения об ошибках и итоги чтения.
//
&НаСервере
Функция ПрочитатьРеестры()
СтрокиРеестров = НоваяТаблицаСтрок();
Ошибки = Новый Массив;
Итоги = ПрочитатьКаталогФайлов(Каталог, СтрокиРеестров, Ошибки);
ТаблицаРеестра.Очистить();
Для Каждого СтрокаРеестра Из СтрокиРеестров Цикл
НоваяСтрока = ТаблицаРеестра.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаРеестра);
КонецЦикла;
ТекстСообщений = СтрСоединить(Ошибки, Символы.ПС);
Если Итоги.ОбработаноФайлов = 0 И Не ЗначениеЗаполнено(ТекстСообщений) Тогда
ТекстСообщений = НСтр("ru = 'В каталоге не найдено ни одного файла реестра.'");
КонецЕсли;
Если Итоги.ПропущеноФайлов > 0 Тогда
ИтогиТекст = СтрШаблон(НСтр("ru = 'Обработано файлов: %1, пропущено: %2.'"),
Итоги.ОбработаноФайлов, Итоги.ПропущеноФайлов);
ТекстСообщений = ИтогиТекст + ?(ЗначениеЗаполнено(ТекстСообщений), Символы.ПС + ТекстСообщений, "");
КонецЕсли;
Возврат Новый Структура("ТекстСообщений", ТекстСообщений);
КонецФункции
&НаСервере
Функция СформироватьПечатнуюФорму()
ТабличныйДокумент = Новый ТабличныйДокумент;
ТабличныйДокумент.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
ТабличныйДокумент.АвтоМасштаб = Истина;
ШрифтОбычный = Новый Шрифт("Arial", 8);
ШрифтЖирный = Новый Шрифт("Arial", 8, Истина);
ШрифтЗаголовка = Новый Шрифт("Arial", 12, Истина);
ЛинияРамки = Новый Линия(ТипЛинииЯчейкиТабличногоДокумента.Сплошная, 1);
Колонки = КолонкиПечати();
КоличествоКолонок = Колонки.Количество();
ИндексСуммы = ИндексКолонкиСуммы(Колонки);
ОбластьЗаголовка = ТабличныйДокумент.Область(1, 1, 1, КоличествоКолонок);
ОбластьЗаголовка.Объединить();
ОбластьЗаголовка.Текст = НСтр("ru = 'Реестр платежей'");
ОбластьЗаголовка.Шрифт = ШрифтЗаголовка;
ОбластьЗаголовка.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
СтрокаШапки = 3;
Для Индекс = 1 По КоличествоКолонок Цикл
Колонка = Колонки[Индекс - 1];
ОбластьЯчейки = ТабличныйДокумент.Область(СтрокаШапки, Индекс);
ОбластьЯчейки.Текст = Колонка.Заголовок;
ОбластьЯчейки.Шрифт = ШрифтЖирный;
ОбластьЯчейки.Обвести(ЛинияРамки, ЛинияРамки, ЛинияРамки, ЛинияРамки);
ОбластьЯчейки.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
ОбластьЯчейки.ШиринаКолонки = Колонка.Ширина;
КонецЦикла;
НомерСтроки = СтрокаШапки + 1;
ИтогоСумма = 0;
Для Каждого СтрокаРеестра Из ТаблицаРеестра Цикл
Для Индекс = 1 По КоличествоКолонок Цикл
Колонка = Колонки[Индекс - 1];
ОбластьЯчейки = ТабличныйДокумент.Область(НомерСтроки, Индекс);
ОбластьЯчейки.Текст = ТекстЗначения(СтрокаРеестра[Колонка.Данные], Колонка.Формат);
ОбластьЯчейки.Шрифт = ШрифтОбычный;
ОбластьЯчейки.Обвести(ЛинияРамки, ЛинияРамки, ЛинияРамки, ЛинияРамки);
Если Колонка.Выравнивание = "Право" Тогда
ОбластьЯчейки.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Право;
КонецЕсли;
КонецЦикла;
ИтогоСумма = ИтогоСумма + СтрокаРеестра.Сумма;
НомерСтроки = НомерСтроки + 1;
КонецЦикла;
ОбластьИтога = ТабличныйДокумент.Область(НомерСтроки, 1, НомерСтроки, ИндексСуммы - 1);
ОбластьИтога.Объединить();
ОбластьИтога.Текст = НСтр("ru = 'ИТОГО:'");
ОбластьИтога.Шрифт = ШрифтЖирный;
ОбластьИтога.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Право;
ОбластьСуммы = ТабличныйДокумент.Область(НомерСтроки, ИндексСуммы);
ОбластьСуммы.Текст = Формат(ИтогоСумма, "ЧДЦ=2; ЧН=0");
ОбластьСуммы.Шрифт = ШрифтЖирный;
ОбластьСуммы.Обвести(ЛинияРамки, ЛинияРамки, ЛинияРамки, ЛинияРамки);
ОбластьСуммы.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Право;
Возврат ТабличныйДокумент;
КонецФункции
&НаСервереБезКонтекста
Функция КолонкиПечати()
Колонки = Новый Массив;
Колонки.Добавить(КолонкаПечати("Файл", "Файл", 22));
Колонки.Добавить(КолонкаПечати("№ ПП", "НомерПП", 8));
Колонки.Добавить(КолонкаПечати("№ распоряжения", "НомерРаспоряжения", 12));
Колонки.Добавить(КолонкаПечати("Дата распоряжения", "ДатаРаспоряжения", 12, "ДЛФ=D"));
Колонки.Добавить(КолонкаПечати("Плательщик", "Плательщик", 28));
Колонки.Добавить(КолонкаПечати("Счёт плательщика", "СчетПлательщика", 20));
Колонки.Добавить(КолонкаПечати("Сумма", "Сумма", 14, "ЧДЦ=2; ЧН=0", "Право"));
Колонки.Добавить(КолонкаПечати("Назначение платежа", "Назначение", 40));
Колонки.Добавить(КолонкаПечати("Статус", "Статус", 7));
Возврат Колонки;
КонецФункции
&НаСервереБезКонтекста
Функция КолонкаПечати(Заголовок, Данные, Ширина, ФорматЗначения = "", Выравнивание = "Лево")
Колонка = Новый Структура;
Колонка.Вставить("Заголовок", Заголовок);
Колонка.Вставить("Данные", Данные);
Колонка.Вставить("Ширина", Ширина);
Колонка.Вставить("Формат", ФорматЗначения);
Колонка.Вставить("Выравнивание", Выравнивание);
Возврат Колонка;
КонецФункции
&НаСервереБезКонтекста
Функция ИндексКолонкиСуммы(Колонки)
Для Индекс = 1 По Колонки.Количество() Цикл
Если Колонки[Индекс - 1].Данные = "Сумма" Тогда
Возврат Индекс;
КонецЕсли;
КонецЦикла;
Возврат Колонки.Количество();
КонецФункции
&НаСервереБезКонтекста
Функция ТекстЗначения(Значение, ФорматЗначения)
Если Значение = Неопределено Тогда
Возврат "";
КонецЕсли;
Если ТипЗнч(Значение) = Тип("Дата") И Не ЗначениеЗаполнено(Значение) Тогда
Возврат "";
КонецЕсли;
Если ЗначениеЗаполнено(ФорматЗначения) Тогда
Возврат Формат(Значение, ФорматЗначения);
КонецЕсли;
Возврат Строка(Значение);
КонецФункции
// Создаёт пустую таблицу строк реестров.
//
// Возвращаемое значение:
// ТаблицаЗначений - колонки строки реестра.
//
&НаСервереБезКонтекста
Функция НоваяТаблицаСтрок()
КвалификаторыСуммы = Новый КвалификаторыЧисла(15, 2);
ОписаниеСуммы = Новый ОписаниеТипов("Число", КвалификаторыСуммы);
ОписаниеСтроки = Новый ОписаниеТипов("Строка");
ОписаниеДаты = Новый ОписаниеТипов("Дата");
ОписаниеНомера = Новый ОписаниеТипов("Число");
Строки = Новый ТаблицаЗначений;
Строки.Колонки.Добавить("Файл", ОписаниеСтроки);
Строки.Колонки.Добавить("НомерПП", ОписаниеСтроки);
Строки.Колонки.Добавить("ДатаПП", ОписаниеДаты);
Строки.Колонки.Добавить("НомерСтроки", ОписаниеНомера);
Строки.Колонки.Добавить("НомерРаспоряжения", ОписаниеСтроки);
Строки.Колонки.Добавить("ДатаРаспоряжения", ОписаниеДаты);
Строки.Колонки.Добавить("Плательщик", ОписаниеСтроки);
Строки.Колонки.Добавить("СчетПлательщика", ОписаниеСтроки);
Строки.Колонки.Добавить("Сумма", ОписаниеСуммы);
Строки.Колонки.Добавить("Назначение", ОписаниеСтроки);
Строки.Колонки.Добавить("Получатель", ОписаниеСтроки);
Строки.Колонки.Добавить("Статус", ОписаниеСтроки);
Возврат Строки;
КонецФункции
// Читает все xml-файлы реестров из каталога и добавляет их строки в общую таблицу.
//
// Параметры:
// Каталог - Строка - путь к каталогу с файлами реестров к платёжным поручениям.
// СтрокиРеестров - ТаблицаЗначений - таблица, созданная функцией НоваяТаблицаСтрок.
// Ошибки - Массив из Строка - в него добавляются сообщения о файлах, которые не удалось прочитать.
//
// Возвращаемое значение:
// Структура - итоги чтения:
// * ОбработаноФайлов - Число - количество прочитанных файлов реестров;
// * ПропущеноФайлов - Число - количество файлов, которые не удалось прочитать.
//
&НаСервереБезКонтекста
Функция ПрочитатьКаталогФайлов(Каталог, СтрокиРеестров, Ошибки)
Итоги = Новый Структура("ОбработаноФайлов, ПропущеноФайлов", 0, 0);
Попытка
Файлы = НайтиФайлы(Каталог, "*.xml");
Исключение
Ошибки.Добавить(СтрШаблон("Каталог %1 недоступен - %2", Каталог, ИнформацияОбОшибке().Описание));
Возврат Итоги;
КонецПопытки;
Для Каждого Файл Из Файлы Цикл
Если Файл.ЭтоКаталог() Тогда
Продолжить;
КонецЕсли;
Если ПрочитатьФайл(Файл.ПолноеИмя, СтрокиРеестров, Ошибки) Тогда
Итоги.ОбработаноФайлов = Итоги.ОбработаноФайлов + 1;
Иначе
Итоги.ПропущеноФайлов = Итоги.ПропущеноФайлов + 1;
КонецЕсли;
КонецЦикла;
Возврат Итоги;
КонецФункции
// Читает один файл реестра к платёжному поручению на общую сумму с реестром.
//
// Параметры:
// ИмяФайла - Строка - полный путь к файлу.
// СтрокиРеестров - ТаблицаЗначений - таблица, созданная функцией НоваяТаблицаСтрок.
// Ошибки - Массив из Строка - в него добавляются сообщения об ошибках чтения.
//
// Возвращаемое значение:
// Булево - Истина, если файл прочитан как реестр.
//
&НаСервереБезКонтекста
Функция ПрочитатьФайл(ИмяФайла, СтрокиРеестров, Ошибки)
ЧтениеXML = Новый ЧтениеXML;
Попытка
ЧтениеXML.ОткрытьФайл(ИмяФайла);
Исключение
Ошибки.Добавить(СтрШаблон("%1: файл не открыт - %2", ИмяФайлаИзПути(ИмяФайла), ИнформацияОбОшибке().Описание));
Возврат Ложь;
КонецПопытки;
Результат = Ложь;
Попытка
Результат = РазобратьРеестр(ЧтениеXML, ИмяФайла, СтрокиРеестров, Ошибки);
Исключение
Ошибки.Добавить(СтрШаблон("%1: ошибка разбора - %2", ИмяФайлаИзПути(ИмяФайла), ИнформацияОбОшибке().Описание));
КонецПопытки;
ЧтениеXML.Закрыть();
Возврат Результат;
КонецФункции
// Разбирает поток XML и добавляет строки реестра в общую таблицу.
//
// Параметры:
// ЧтениеXML - ЧтениеXML - открытый поток чтения.
// ИмяФайла - Строка - путь к файлу, для сообщений об ошибках.
// СтрокиРеестров - ТаблицаЗначений - таблица, созданная функцией НоваяТаблицаСтрок.
// Ошибки - Массив из Строка - в него добавляются сообщения об ошибках.
//
// Возвращаемое значение:
// Булево - Истина, если файл прочитан как реестр.
//
&НаСервереБезКонтекста
Функция РазобратьРеестр(ЧтениеXML, ИмяФайла, СтрокиРеестров, Ошибки)
Шапка = НоваяШапка();
СтрокиФайла = НоваяТаблицаСтрок();
Если Не ПрочитатьУзлы(ЧтениеXML, Шапка, СтрокиФайла) Тогда
Ошибки.Добавить(СтрШаблон("%1: пропущен, это не реестр к платёжному поручению", ИмяФайлаИзПути(ИмяФайла)));
Возврат Ложь;
КонецЕсли;
ДобавитьСтрокиФайла(СтрокиФайла, Шапка, ИмяФайла, СтрокиРеестров, Ошибки);
Возврат Истина;
КонецФункции
// Читает узлы XML, заполняя шапку реестра и строки файла.
//
// Параметры:
// ЧтениеXML - ЧтениеXML - открытый поток чтения.
// Шапка - Структура - шапка реестра.
// СтрокиФайла - ТаблицаЗначений - строки текущего файла.
//
// Возвращаемое значение:
// Булево - Истина, если корневой элемент соответствует реестру.
//
&НаСервереБезКонтекста
Функция ПрочитатьУзлы(ЧтениеXML, Шапка, СтрокиФайла)
ЭтоРеестр = Ложь;
ТекущаяСтрока = Неопределено;
ИмяЭлемента = "";
Пока ЧтениеXML.Прочитать() Цикл
ТипУзла = ЧтениеXML.ТипУзла;
Если ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
ИмяЭлемента = ЧтениеXML.Имя;
Если ИмяЭлемента = "ProcessRegPayOrder" Тогда
ЭтоРеестр = Истина;
КонецЕсли;
Если ИмяЭлемента = "RegPP" Тогда
ТекущаяСтрока = СтрокиФайла.Добавить();
КонецЕсли;
ИначеЕсли ТипУзла = ТипУзлаXML.Текст Тогда
Значение = СокрЛП(ЧтениеXML.Значение);
Если ТекущаяСтрока = Неопределено Тогда
ЗаполнитьШапку(Шапка, ИмяЭлемента, Значение);
Иначе
ЗаполнитьСтроку(ТекущаяСтрока, Шапка, ИмяЭлемента, Значение);
КонецЕсли;
ИначеЕсли ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
Если ЧтениеXML.Имя = "RegPP" Тогда
ТекущаяСтрока = Неопределено;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат ЭтоРеестр;
КонецФункции
// Переносит строки файла в общую таблицу и сверяет их сумму с суммой платёжного поручения.
//
// Параметры:
// СтрокиФайла - ТаблицаЗначений - строки текущего файла.
// Шапка - Структура - шапка реестра.
// ИмяФайла - Строка - путь к файлу, для сообщений об ошибках.
// СтрокиРеестров - ТаблицаЗначений - общая таблица строк реестров.
// Ошибки - Массив из Строка - в него добавляются сообщения об ошибках.
//
&НаСервереБезКонтекста
Процедура ДобавитьСтрокиФайла(СтрокиФайла, Шапка, ИмяФайла, СтрокиРеестров, Ошибки)
СуммаСтрок = 0;
Для Каждого СтрокаФайла Из СтрокиФайла Цикл
СтрокаФайла.Файл = ИмяФайлаИзПути(ИмяФайла);
СтрокаФайла.НомерПП = Шапка.НомерПП;
СтрокаФайла.ДатаПП = Шапка.ДатаПП;
СтрокаФайла.Получатель = Шапка.Получатель;
СуммаСтрок = СуммаСтрок + СтрокаФайла.Сумма;
НоваяСтрока = СтрокиРеестров.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаФайла);
КонецЦикла;
Если Шапка.СуммаПП <> 0 И СуммаСтрок <> Шапка.СуммаПП Тогда
Ошибки.Добавить(СтрШаблон("%1: сумма строк %2 не равна сумме платёжного поручения %3",
ИмяФайлаИзПути(ИмяФайла), Формат(СуммаСтрок, "ЧДЦ=2; ЧН=0"), Формат(Шапка.СуммаПП, "ЧДЦ=2; ЧН=0")));
КонецЕсли;
КонецПроцедуры
// Возвращает пустую шапку платёжного поручения.
//
// Возвращаемое значение:
// Структура - реквизиты шапки реестра.
//
&НаСервереБезКонтекста
Функция НоваяШапка()
Шапка = Новый Структура;
Шапка.Вставить("НомерПП", "");
Шапка.Вставить("ДатаПП", Дата(1, 1, 1));
Шапка.Вставить("СуммаПП", 0);
Шапка.Вставить("НазначениеПП", "");
Шапка.Вставить("Получатель", "");
Шапка.Вставить("Исполнитель", "");
Шапка.Вставить("Телефон", "");
Возврат Шапка;
КонецФункции
// Заполняет реквизит шапки по имени элемента XML.
//
// Параметры:
// Шапка - Структура - шапка реестра.
// ИмяЭлемента - Строка - имя элемента XML.
// Значение - Строка - текст элемента.
//
&НаСервереБезКонтекста
Процедура ЗаполнитьШапку(Шапка, ИмяЭлемента, Значение)
Если ИмяЭлемента = "NOM_PP" Тогда
Шапка.НомерПП = Значение;
КонецЕсли;
Если ИмяЭлемента = "DATE_PP" Тогда
Шапка.ДатаПП = РазобратьДату(Значение);
КонецЕсли;
Если ИмяЭлемента = "SUM_PP" Тогда
Шапка.СуммаПП = РазобратьСумму(Значение);
КонецЕсли;
Если ИмяЭлемента = "PURPOSE_PP" Тогда
Шапка.НазначениеПП = Значение;
КонецЕсли;
Если ИмяЭлемента = "FIO_ISP" Тогда
Шапка.Исполнитель = Значение;
КонецЕсли;
Если ИмяЭлемента = "TEL_ISP" Тогда
Шапка.Телефон = Значение;
КонецЕсли;
КонецПроцедуры
// Заполняет реквизит строки реестра по имени элемента XML.
//
// Параметры:
// Строка - СтрокаТаблицыЗначений - строка реестра.
// Шапка - Структура - шапка реестра, заполняется получателем средств.
// ИмяЭлемента - Строка - имя элемента XML.
// Значение - Строка - текст элемента.
//
&НаСервереБезКонтекста
Процедура ЗаполнитьСтроку(Строка, Шапка, ИмяЭлемента, Значение)
Если ИмяЭлемента = "NAME_RCV" Тогда
Шапка.Получатель = Значение;
КонецЕсли;
Если ИмяЭлемента = "NOM_LINE" И ЗначениеЗаполнено(Значение) Тогда
Строка.НомерСтроки = Число(Значение);
КонецЕсли;
Если ИмяЭлемента = "NOM_PAY_DOC" Тогда
Строка.НомерРаспоряжения = Значение;
КонецЕсли;
Если ИмяЭлемента = "DATE_PAY_DOC" Тогда
Строка.ДатаРаспоряжения = РазобратьДату(Значение);
КонецЕсли;
Если ИмяЭлемента = "DATE_REESTR_PP" И Не ЗначениеЗаполнено(Строка.ДатаРаспоряжения) Тогда
Строка.ДатаРаспоряжения = РазобратьДату(Значение);
КонецЕсли;
Если ИмяЭлемента = "SUM_REESTR_PP" Тогда
Строка.Сумма = РазобратьСумму(Значение);
КонецЕсли;
Если ИмяЭлемента = "NAME_PLAT" Тогда
Строка.Плательщик = ИмяПлательщика(Значение);
КонецЕсли;
Если ИмяЭлемента = "FIO_PLAT" И Не ЗначениеЗаполнено(Строка.Плательщик) Тогда
Строка.Плательщик = Значение;
КонецЕсли;
Если ИмяЭлемента = "NOM_LS_PLAT" Тогда
Строка.СчетПлательщика = Значение;
КонецЕсли;
Если ИмяЭлемента = "PURPOSE" Тогда
Строка.Назначение = Значение;
КонецЕсли;
Если ИмяЭлемента = "PAYSTATUS" Тогда
Строка.Статус = Значение;
КонецЕсли;
КонецПроцедуры
// Извлекает имя плательщика из строки вида "ФИО//адрес//".
//
// Параметры:
// Значение - Строка - значение элемента NAME_PLAT.
//
// Возвращаемое значение:
// Строка - имя плательщика без адреса.
//
&НаСервереБезКонтекста
Функция ИмяПлательщика(Значение)
Если Не ЗначениеЗаполнено(Значение) Тогда
Возврат "";
КонецЕсли;
Части = СтрРазделить(Значение, "//", Ложь);
Если Части.Количество() = 0 Тогда
Возврат "";
КонецЕсли;
Возврат СокрЛП(Части[0]);
КонецФункции
// Преобразует сумму в копейках из файла в рубли.
//
// Параметры:
// Значение - Строка - значение элемента с суммой в копейках.
//
// Возвращаемое значение:
// Число - сумма в рублях.
//
&НаСервереБезКонтекста
Функция РазобратьСумму(Значение)
Если Не ЗначениеЗаполнено(Значение) Тогда
Возврат 0;
КонецЕсли;
СтрокаСуммы = СтрЗаменить(СтрЗаменить(Значение, " ", ""), Символ(160), "");
Если Не СтрПодобнаПоРегулярномуВыражению(СтрокаСуммы, "^-?[0-9]+$") Тогда
Возврат 0;
КонецЕсли;
Возврат Число(СтрокаСуммы) / 100;
КонецФункции
// Преобразует дату из формата ГГГГ-ММ-ДД в дату.
//
// Параметры:
// Значение - Строка - значение элемента с датой.
//
// Возвращаемое значение:
// Дата - прочитанная дата, при ошибке - пустая дата.
//
&НаСервереБезКонтекста
Функция РазобратьДату(Значение)
ПустаяДата = Дата(1, 1, 1);
Если Не ЗначениеЗаполнено(Значение) Тогда
Возврат ПустаяДата;
КонецЕсли;
Если Не СтрПодобнаПоРегулярномуВыражению(Значение, "^[0-9]{4}-[0-9]{2}-[0-9]{2}") Тогда
Возврат ПустаяДата;
КонецЕсли;
Части = СтрРазделить(Значение, "-");
Попытка
Возврат Дата(Число(Части[0]), Число(Части[1]), Число(Лев(Части[2], 2)));
Исключение
Возврат ПустаяДата;
КонецПопытки;
КонецФункции
// Возвращает имя файла без пути.
//
// Параметры:
// Путь - Строка - полный путь к файлу.
//
// Возвращаемое значение:
// Строка - имя файла с расширением.
//
&НаСервереБезКонтекста
Функция ИмяФайлаИзПути(Путь)
Части = СтрРазделить(Путь, ПолучитьРазделительПути());
Возврат Части[Части.Количество() - 1];
КонецФункции
#КонецОбласти
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:ExternalDataProcessor xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="61a311a9-1805-4eac-9d9a-09162e9958b4">
<producedTypes>
<objectType typeId="f41ce4fe-2d25-4e4f-914e-be53ce98d993" valueTypeId="3e58cf5e-ff31-4485-a4ec-dee49878a22f"/>
</producedTypes>
<name>ПросмотрРеестровПлатежей</name>
<synonym>
<key>ru</key>
<value>Просмотр реестров платежей</value>
</synonym>
<containedObjects classId="c3831ec8-d8d5-4f93-8a22-f9bfae07327f" objectId="f05660b4-4ee8-43bd-9d49-f75b911cb5a8"/>
<defaultForm>ExternalDataProcessor.ПросмотрРеестровПлатежей.Form.Форма</defaultForm>
<forms uuid="65082154-b36d-4815-8818-6e5b9c5935d1">
<name>Форма</name>
<synonym>
<key>ru</key>
<value>Форма</value>
</synonym>
<usePurposes>PersonalComputer</usePurposes>
<usePurposes>MobileDevice</usePurposes>
</forms>
</mdclass:ExternalDataProcessor>