Загрузка данных
////////////////////
// ЧАСТЬ 1. Общий модуль РаботаСФормой (флаги: Сервер, Вызов сервера — НЕ нужен)
//
// Точка входа для фонового задания — ЗагрузитьЧеки(ПараметрыЗагрузки).
// Все сообщения пользователю заменены на таблицу-лог, которая возвращается
// в результате и выводится на форме.
////////////////////////////////////////////////////////////////////////////////
#Область ПрограммныйИнтерфейс
// Конструктор параметров загрузки. Заполняется на форме, целиком уезжает в фон.
//
// Возвращаемое значение:
// Структура:
// * ДатаНачала - Дата
// * ДатаОкончания - Дата
// * Организация - СправочникСсылка.Организации
// * ИНН - Строка
// * НовыйАлгоритм - Булево
// * СоответствиеСкладов - ТаблицаЗначений - колонки СкладЗПЧ, СкладБП
// * ТолькоПодбор - Булево - Истина: только подобрать номенклатуру,
// документы не создавать (режим проверки)
//
Функция ПараметрыЗагрузкиЧеков() Экспорт
Параметры = Новый Структура;
Параметры.Вставить("ДатаНачала", '00010101');
Параметры.Вставить("ДатаОкончания", '00010101');
Параметры.Вставить("Организация", Справочники.Организации.ПустаяСсылка());
Параметры.Вставить("ИНН", "");
Параметры.Вставить("НовыйАлгоритм", Истина);
Параметры.Вставить("СоответствиеСкладов", НоваяТаблицаСоответствияСкладов());
Параметры.Вставить("ТолькоПодбор", Ложь);
Возврат Параметры;
КонецФункции
Функция НоваяТаблицаСоответствияСкладов() Экспорт
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("СкладЗПЧ");
Таблица.Колонки.Добавить("СкладБП");
Возврат Таблица;
КонецФункции
// Точка входа фонового задания.
//
// Параметры:
// ПараметрыЗагрузки - см. ПараметрыЗагрузкиЧеков
//
// Возвращаемое значение:
// Структура:
// * Лог - ТаблицаЗначений
// * СозданныеДокументы - Массив из ДокументСсылка.ОтчетОРозничныхПродажах
// * ОбработаноЧеков - Число
// * ЕстьОшибки - Булево
//
Функция ЗагрузитьЧеки(ПараметрыЗагрузки) Экспорт
Результат = Новый Структура;
Результат.Вставить("Лог", НоваяТаблицаЛога());
Результат.Вставить("СозданныеДокументы", Новый Массив);
Результат.Вставить("ОбработаноЧеков", 0);
Результат.Вставить("ЕстьОшибки", Ложь);
// --- Этап 1: получение данных из ЗПЧ ------------------------------------
ДлительныеОперации.СообщитьПрогресс(1, НСтр("ru = 'Получение данных из ЗПЧ...'"));
Попытка
ДанныеДокументов = ПолучитьЧекиИзЗПЧ(ПараметрыЗагрузки);
Исключение
ДобавитьВЛог(Результат.Лог, , , НСтр("ru = 'Ошибка получения данных из ЗПЧ: '")
+ ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), Истина);
Результат.ЕстьОшибки = Истина;
Возврат Результат;
КонецПопытки;
Если ДанныеДокументов.Количество() = 0 Тогда
ДобавитьВЛог(Результат.Лог, , , НСтр("ru = 'За указанный период чеков не получено'"), Ложь);
Возврат Результат;
КонецЕсли;
// --- Этап 2: подбор номенклатуры ----------------------------------------
ЗаполнитьНоменклатуруЧеков(ДанныеДокументов, ПараметрыЗагрузки, Результат.Лог);
Результат.ОбработаноЧеков = ДанныеДокументов.Количество();
// --- Этап 3: создание документов ----------------------------------------
Если НЕ ПараметрыЗагрузки.ТолькоПодбор Тогда
СоздатьДокументыПоЧекам(ДанныеДокументов, ПараметрыЗагрузки, Результат);
КонецЕсли;
ДлительныеОперации.СообщитьПрогресс(100, НСтр("ru = 'Готово'"));
Для Каждого СтрокаЛога Из Результат.Лог Цикл
Если СтрокаЛога.ЭтоОшибка Тогда
Результат.ЕстьОшибки = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция НоваяТаблицаЛога()
Лог = Новый ТаблицаЗначений;
Лог.Колонки.Добавить("Чек", Новый ОписаниеТипов("Строка"));
Лог.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("Строка"));
Лог.Колонки.Добавить("Текст", Новый ОписаниеТипов("Строка"));
Лог.Колонки.Добавить("ЭтоОшибка", Новый ОписаниеТипов("Булево"));
Возврат Лог;
КонецФункции
Процедура ДобавитьВЛог(Лог, Чек = "", Номенклатура = "", Текст = "", ЭтоОшибка = Ложь)
Стр = Лог.Добавить();
Стр.Чек = Строка(Чек);
Стр.Номенклатура = Строка(Номенклатура);
Стр.Текст = Текст;
Стр.ЭтоОшибка = ЭтоОшибка;
КонецПроцедуры
////////////////////////////////////////////////////////////////////////////////
// Подбор номенклатуры
Процедура ЗаполнитьНоменклатуруЧеков(ДанныеДокументов, ПараметрыЗагрузки, Лог)
// Ключ: "GUID склада|GUID номенклатуры", значение: количество,
// уже разобранное строками текущего сеанса загрузки.
Потрачено = Новый Соответствие;
// Документы разбираем в хронологическом порядке: расход более позднего
// чека не должен вычитаться из остатка более раннего.
ДанныеДокументов = ДокументыПоВозрастаниюДаты(ДанныеДокументов);
ВсегоДокументов = ДанныеДокументов.Количество();
НомерДокумента = 0;
Для Каждого СтрокаДокумента Из ДанныеДокументов Цикл
НомерДокумента = НомерДокумента + 1;
// Прогресс отдаём по документам, а не по строкам: на 300 строк
// это сотни лишних записей во временное хранилище.
ДлительныеОперации.СообщитьПрогресс(
5 + Окр(50 * НомерДокумента / ВсегоДокументов),
СтрШаблон(НСтр("ru = 'Подбор номенклатуры: чек %1 из %2'"),
НомерДокумента, ВсегоДокументов));
ПредставлениеЧека = Строка(СтрокаДокумента.НомерДокумента);
СкладБП = СкладБППоСкладуЗПЧ(СтрокаДокумента.Склад, ПараметрыЗагрузки.СоответствиеСкладов);
// ОРП создаётся концом дня — остаток должен считаться на тот же момент,
// иначе подбор и проверка при проведении разойдутся.
ДатаОстатков = КонецДня(Дата(СтрокаДокумента.ДатаДокумента));
НовыеТовары = Новый Массив;
Для Каждого СтрокаТовара Из СтрокаДокумента.Товары Цикл
Требуется = СтрокаТовара.Количество;
Кандидаты = КандидатыНоменклатуры(СтрокаТовара, СкладБП, ДатаОстатков, Лог, ПредставлениеЧека);
ЗаполнитьПриоритетыКандидатов(Кандидаты, СтрокаТовара);
ПрименитьРанееПотраченное(Кандидаты, Потрачено, СкладБП);
Кандидаты.Сортировать("Приоритет Возр, Остаток Убыв");
Если Кандидаты.Количество() = 0 Тогда
ДобавитьВЛог(Лог, ПредставлениеЧека, СтрокаТовара.Номенклатура,
СтрШаблон(НСтр("ru = 'Не найдена номенклатура БП (кат. номер %1)'"),
СтрокаТовара.КаталожныйНомерНоменклатуры), Истина);
ЧастьСтроки = КопияСтрокиТовара(СтрокаТовара, Требуется);
ЧастьСтроки.Вставить("НоменклатураБП", Справочники.Номенклатура.ПустаяСсылка());
НовыеТовары.Добавить(ЧастьСтроки);
Продолжить;
КонецЕсли;
ОбщийСвободный = Кандидаты.Итог("Остаток");
Если ОбщийСвободный < Требуется Тогда
ДобавитьВЛог(Лог, ПредставлениеЧека, СтрокаТовара.Номенклатура,
СтрШаблон(НСтр("ru = 'Запрашиваемое количество %1 превышает свободный остаток %2'"),
Требуется, ОбщийСвободный), Истина);
КонецЕсли;
// 1) Пытаемся закрыть строку одной карточкой — приоритетной из тех,
// у кого хватает собственного свободного остатка.
ПодходящийКандидат = Неопределено;
Для Каждого Кандидат Из Кандидаты Цикл
Если Кандидат.Остаток >= Требуется Тогда
ПодходящийКандидат = Кандидат;
Прервать;
КонецЕсли;
КонецЦикла;
Если ПодходящийКандидат <> Неопределено Тогда
СписатьОстаток(Потрачено, СкладБП, ПодходящийКандидат.Номенклатура, Требуется);
ЧастьСтроки = КопияСтрокиТовара(СтрокаТовара, Требуется);
ЧастьСтроки.Вставить("НоменклатураБП", ПодходящийКандидат.Номенклатура);
НовыеТовары.Добавить(ЧастьСтроки);
Продолжить;
КонецЕсли;
// 2) Одной карточкой не закрывается — разбиваем строку по кандидатам.
ОсталосьРаспределить = Требуется;
Для Каждого Кандидат Из Кандидаты Цикл
Если ОсталосьРаспределить <= 0 Тогда
Прервать;
КонецЕсли;
Если Кандидат.Остаток <= 0 Тогда
Продолжить;
КонецЕсли;
Взято = ?(Кандидат.Остаток < ОсталосьРаспределить, Кандидат.Остаток, ОсталосьРаспределить);
ЧастьСтроки = КопияСтрокиТовара(СтрокаТовара, Взято);
ЧастьСтроки.Вставить("НоменклатураБП", Кандидат.Номенклатура);
НовыеТовары.Добавить(ЧастьСтроки);
СписатьОстаток(Потрачено, СкладБП, Кандидат.Номенклатура, Взято);
ОсталосьРаспределить = ОсталосьРаспределить - Взято;
ДобавитьВЛог(Лог, ПредставлениеЧека, СтрокаТовара.Номенклатура,
СтрШаблон(НСтр("ru = 'Строка разбита: %1 шт на карточку ""%2""'"),
Взято, Кандидат.Наименование), Ложь);
КонецЦикла;
// 3) Хвост, который не покрыт ничем: вешаем на самого приоритетного
// кандидата, чтобы не потерять сумму чека.
Если ОсталосьРаспределить > 0 Тогда
ЧастьСтроки = КопияСтрокиТовара(СтрокаТовара, ОсталосьРаспределить);
ЧастьСтроки.Вставить("НоменклатураБП", Кандидаты[0].Номенклатура);
НовыеТовары.Добавить(ЧастьСтроки);
СписатьОстаток(Потрачено, СкладБП, Кандидаты[0].Номенклатура, ОсталосьРаспределить);
КонецЕсли;
КонецЦикла;
СтрокаДокумента.Вставить("Товары", НовыеТовары);
КонецЦикла;
КонецПроцедуры
// Сортировка входящих документов по дате по возрастанию.
Функция ДокументыПоВозрастаниюДаты(ДанныеДокументов)
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Документ");
Таблица.Колонки.Добавить("Дата", Новый ОписаниеТипов("Дата"));
Для Каждого СтрокаДокумента Из ДанныеДокументов Цикл
Стр = Таблица.Добавить();
Стр.Документ = СтрокаДокумента;
Стр.Дата = Дата(СтрокаДокумента.ДатаДокумента);
КонецЦикла;
Таблица.Сортировать("Дата Возр");
Результат = Новый Массив;
Для Каждого Стр Из Таблица Цикл
Результат.Добавить(Стр.Документ);
КонецЦикла;
Возврат Результат;
КонецФункции
// Приоритет: 0 — точное совпадение с наименованием чека,
// 1 — пересечение с наименованием поставщика, 2 — прочее.
Процедура ЗаполнитьПриоритетыКандидатов(Кандидаты, СтрокаТовара)
НаимЧека = ВРег(СокрЛП(Строка(СтрокаТовара.Номенклатура)));
НаимПоставщика = "";
Если СтрокаТовара.Свойство("НоменклатураПоставщика")
И ЗначениеЗаполнено(СтрокаТовара.НоменклатураПоставщика) Тогда
НаимПоставщика = ВРег(СокрЛП(Строка(СтрокаТовара.НоменклатураПоставщика)));
КонецЕсли;
Для Каждого Кандидат Из Кандидаты Цикл
НаимКандидата = ВРег(СокрЛП(Кандидат.Наименование));
Если НаимКандидата = НаимЧека Тогда
Кандидат.Приоритет = 0;
ИначеЕсли НЕ ПустаяСтрока(НаимПоставщика)
И (СтрНайти(НаимПоставщика, НаимКандидата) > 0
ИЛИ СтрНайти(НаимКандидата, НаимПоставщика) > 0) Тогда
Кандидат.Приоритет = 1;
Иначе
Кандидат.Приоритет = 2;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Уменьшает остаток кандидата на количество, уже разобранное
// предыдущими строками текущего сеанса загрузки.
Процедура ПрименитьРанееПотраченное(Кандидаты, Потрачено, Склад)
Для Каждого Кандидат Из Кандидаты Цикл
Расход = Потрачено.Получить(КлючОстатка(Склад, Кандидат.Номенклатура));
Если Расход <> Неопределено Тогда
Кандидат.Остаток = Кандидат.Остаток - Расход;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура СписатьОстаток(Потрачено, Склад, Номенклатура, Количество)
Ключ = КлючОстатка(Склад, Номенклатура);
Расход = Потрачено.Получить(Ключ);
Если Расход = Неопределено Тогда
Расход = 0;
КонецЕсли;
Потрачено.Вставить(Ключ, Расход + Количество);
КонецПроцедуры
Функция КлючОстатка(Склад, Номенклатура)
Возврат Строка(Склад.УникальныйИдентификатор()) + "|"
+ Строка(Номенклатура.УникальныйИдентификатор());
КонецФункции
// Копия структуры строки товара с пересчётом количества и зависимых сумм.
Функция КопияСтрокиТовара(СтрокаТовара, Количество)
Копия = Новый Структура;
Для Каждого КлючИЗначение Из СтрокаТовара Цикл
Копия.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение);
КонецЦикла;
ИсходноеКоличество = СтрокаТовара.Количество;
Копия.Вставить("Количество", Количество);
Если ИсходноеКоличество = 0 Тогда
Возврат Копия;
КонецЕсли;
Доля = Количество / ИсходноеКоличество;
Если Копия.Свойство("Сумма") Тогда
Копия.Вставить("Сумма", Окр(СтрокаТовара.Сумма * Доля, 2));
КонецЕсли;
Если Копия.Свойство("СуммаНДС") Тогда
Копия.Вставить("СуммаНДС", Окр(СтрокаТовара.СуммаНДС * Доля, 2));
КонецЕсли;
Возврат Копия;
КонецФункции
Функция КандидатыНоменклатуры(СтрокаТовара, Склад, ДатаОстатков, Лог, ПредставлениеЧека)
КатНомер = Лев(СокрЛП(Строка(СтрокаТовара.КаталожныйНомерНоменклатуры)), 25);
Наименование = СокрЛП(Строка(СтрокаТовара.Номенклатура));
НаимПоставщика = "";
Если СтрокаТовара.Свойство("НоменклатураПоставщика")
И ЗначениеЗаполнено(СтрокаТовара.НоменклатураПоставщика) Тогда
НаимПоставщика = СокрЛП(Строка(СтрокаТовара.НоменклатураПоставщика));
КонецЕсли;
Результат = Новый ТаблицаЗначений;
Результат.Колонки.Добавить("Номенклатура");
Результат.Колонки.Добавить("Наименование");
Результат.Колонки.Добавить("Остаток", Новый ОписаниеТипов("Число"));
Результат.Колонки.Добавить("Приоритет", Новый ОписаниеТипов("Число"));
ИндексСклада = ИндексСубконтоСклады();
ПрименятьСклад = (ИндексСклада > 0) И ЗначениеЗаполнено(Склад);
УсловиеСклада = ?(ПрименятьСклад,
СтрШаблон(" И Субконто%1 = &Склад", Строка(ИндексСклада)), "");
Запрос = Новый Запрос;
Запрос.Текст = СтрЗаменить(
"ВЫБРАТЬ
| Ном.Ссылка КАК Номенклатура,
| Ном.Наименование КАК Наименование
|ПОМЕСТИТЬ ВТКандидаты
|ИЗ
| Справочник.Номенклатура КАК Ном
|ГДЕ
| (Ном.Артикул = &КатНомер
| ИЛИ Ном.Наименование = &Наименование
| ИЛИ (&ЕстьНаимПоставщика И Ном.Наименование = &НаименованиеПоставщика))
| И НЕ Ном.ПометкаУдаления
| И НЕ Ном.ЭтоГруппа
|;
|////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| К.Номенклатура КАК Номенклатура,
| К.Наименование КАК Наименование,
| ЕСТЬNULL(Ост.КоличествоОстатокДт, 0) КАК Остаток
|ИЗ
| ВТКандидаты КАК К
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.Остатки(
| &ДатаОстатков,
| Счет = &Счет,
| ,
| Субконто1 В (ВЫБРАТЬ Т.Номенклатура ИЗ ВТКандидаты КАК Т)%Склад) КАК Ост
| ПО К.Номенклатура = Ост.Субконто1
|
|УПОРЯДОЧИТЬ ПО
| Остаток УБЫВ,
| Наименование",
"%Склад", УсловиеСклада);
Запрос.УстановитьПараметр("КатНомер", КатНомер);
Запрос.УстановитьПараметр("Наименование", Наименование);
Запрос.УстановитьПараметр("НаименованиеПоставщика", НаимПоставщика);
Запрос.УстановитьПараметр("ЕстьНаимПоставщика", НЕ ПустаяСтрока(НаимПоставщика));
Запрос.УстановитьПараметр("ДатаОстатков", ДатаОстатков);
Запрос.УстановитьПараметр("Счет", ПланыСчетов.Хозрасчетный.НайтиПоКоду("41.01"));
Если ПрименятьСклад Тогда
Запрос.УстановитьПараметр("Склад", Склад);
КонецЕсли;
Попытка
Выборка = Запрос.Выполнить().Выбрать();
Исключение
ДобавитьВЛог(Лог, ПредставлениеЧека, Наименование,
СтрШаблон(НСтр("ru = 'Ошибка запроса кандидатов по артикулу %1: %2'"),
КатНомер, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())), Истина);
Возврат Результат;
КонецПопытки;
Пока Выборка.Следующий() Цикл
Стр = Результат.Добавить();
Стр.Номенклатура = Выборка.Номенклатура;
Стр.Наименование = Выборка.Наименование;
Стр.Остаток = Выборка.Остаток;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ИндексСубконтоСклады()
Счет = ПланыСчетов.Хозрасчетный.НайтиПоКоду("41.01");
Если НЕ ЗначениеЗаполнено(Счет) Тогда
Возврат 0;
КонецЕсли;
ВидСклады = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Склады;
Индекс = 0;
Для Каждого СтрокаСубконто Из Счет.ВидыСубконто Цикл
Индекс = Индекс + 1;
Если СтрокаСубконто.ВидСубконто = ВидСклады Тогда
Возврат Индекс;
КонецЕсли;
КонецЦикла;
Возврат 0;
КонецФункции
// Соответствие складов теперь приходит параметром, а не читается из реквизита формы.
Функция СкладБППоСкладуЗПЧ(СкладЗПЧ, СоответствиеСкладов)
Найденные = СоответствиеСкладов.НайтиСтроки(Новый Структура("СкладЗПЧ", СкладЗПЧ));
Если Найденные.Количество() > 0 Тогда
Возврат Найденные[0].СкладБП;
КонецЕсли;
Возврат Справочники.Склады.ПустаяСсылка();
КонецФункции
////////////////////////////////////////////////////////////////////////////////
// Заглушки под существующий код — подставьте свои реализации.
Функция ПолучитьЧекиИзЗПЧ(ПараметрыЗагрузки)
// ЗДЕСЬ: перенесённый HTTP-запрос к ЗПЧ + разбор JSON.
// Возвращает массив структур документов (как раньше — ДанныеДокументов).
ВызватьИсключение НСтр("ru = 'Не реализовано: перенесите сюда получение чеков по HTTP'");
КонецФункции
Процедура СоздатьДокументыПоЧекам(ДанныеДокументов, ПараметрыЗагрузки, Результат)
ВсегоДокументов = ДанныеДокументов.Количество();
Номер = 0;
Для Каждого СтрокаДокумента Из ДанныеДокументов Цикл
Номер = Номер + 1;
ДлительныеОперации.СообщитьПрогресс(
55 + Окр(45 * Номер / ВсегоДокументов),
СтрШаблон(НСтр("ru = 'Создание документов: %1 из %2'"), Номер, ВсегоДокументов));
// Каждый документ — отдельная транзакция. Не заворачивать весь цикл
// в одну: в файловой базе это заблокирует базу на всё время загрузки.
Попытка
// ЗДЕСЬ: создание и проведение ОРП по СтрокаДокумента.
// Результат.СозданныеДокументы.Добавить(ДокументСсылка);
Исключение
ДобавитьВЛог(Результат.Лог, СтрокаДокумента.НомерДокумента, ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), Истина);
КонецПопытки;
КонецЦикла;
КонецПроцедуры
#КонецОбласти
////////////////////////////////////////////////////////////////////////////////
// ЧАСТЬ 2. Модуль формы «Форма настроек загрузки из ЗПЧ»
//
// Реквизиты формы, которые надо добавить:
// ИдентификаторЗадания - УникальныйИдентификатор
// АдресРезультата - Строка
// ПроцентВыполнения - Число (0..100)
// ТекстВыполнения - Строка
// ЛогЗагрузки - ТаблицаЗначений (Чек, Номенклатура, Текст, ЭтоОшибка)
//
// Элементы формы:
// ГруппаПрогресс (Группа, обычная, Видимость = Ложь)
// Индикатор — поле с типом «Индикатор», данные = ПроцентВыполнения
// НадписьПрогресс — поле надписи, данные = ТекстВыполнения
// ОтменитьЗагрузку — кнопка
// ЛогЗагрузки — таблица формы, у колонки Текст условное оформление по ЭтоОшибка
////////////////////////////////////////////////////////////////////////////////
&НаКлиенте
Процедура ЗагрузитьЧеки(Команда)
Если ЗначениеЗаполнено(ИдентификаторЗадания) Тогда
ПоказатьПредупреждение(, НСтр("ru = 'Загрузка уже выполняется'"));
Возврат;
КонецЕсли;
ДлительнаяОперация = НачатьЗагрузкуЧеков();
ИдентификаторЗадания = ДлительнаяОперация.ИдентификаторЗадания;
АдресРезультата = ДлительнаяОперация.АдресРезультата;
ПоказатьИндикатор(Истина, 0, НСтр("ru = 'Запуск...'"));
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
// Своя индикация на форме, поэтому стандартное окно ожидания не выводим.
ПараметрыОжидания.ВыводитьОкноОжидания = Ложь;
ПараметрыОжидания.ВыводитьПрогрессВыполнения = Истина;
ПараметрыОжидания.Интервал = 1;
ПараметрыОжидания.ОповещениеОПрогрессеВыполнения =
Новый ОписаниеОповещения("ЗагрузкаЧековПрогресс", ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация,
Новый ОписаниеОповещения("ЗагрузкаЧековЗавершена", ЭтотОбъект), ПараметрыОжидания);
КонецПроцедуры
&НаСервере
Функция НачатьЗагрузкуЧеков()
ЛогЗагрузки.Очистить();
ПараметрыЗагрузки = РаботаСФормой.ПараметрыЗагрузкиЧеков();
ПараметрыЗагрузки.ДатаНачала = НачалоДня(ПериодЧеков.ДатаНачала);
ПараметрыЗагрузки.ДатаОкончания = КонецДня(ПериодЧеков.ДатаОкончания);
ПараметрыЗагрузки.Организация = Организация;
ПараметрыЗагрузки.ИНН = ИНН;
ПараметрыЗагрузки.НовыйАлгоритм = НовыйАлгоритм;
ПараметрыЗагрузки.ТолькоПодбор = ТолькоПодбор;
// Реквизиты формы в фон не уезжают — таблицу соответствия копируем в параметры.
ПараметрыЗагрузки.СоответствиеСкладов =
РеквизитФормыВЗначение("СоответствиеСкладовЧеки");
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияФункции(УникальныйИдентификатор);
ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = 'Загрузка чеков из ЗПЧ'");
// Без этого в файловой базе и в режиме отладки задание выполнится
// синхронно, и прогресса на форме не будет.
ПараметрыВыполнения.ЗапуститьВФоне = Истина;
Возврат ДлительныеОперации.ВыполнитьФункцию(ПараметрыВыполнения,
"РаботаСФормой.ЗагрузитьЧеки", ПараметрыЗагрузки);
КонецФункции
&НаКлиенте
Процедура ЗагрузкаЧековПрогресс(Состояние, ДополнительныеПараметры) Экспорт
Если Состояние.Прогресс = Неопределено Тогда
Возврат;
КонецЕсли;
ПроцентВыполнения = Состояние.Прогресс.Процент;
Если ЗначениеЗаполнено(Состояние.Прогресс.Текст) Тогда
ТекстВыполнения = Состояние.Прогресс.Текст;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ЗагрузкаЧековЗавершена(Результат, ДополнительныеПараметры) Экспорт
ИдентификаторЗадания = Неопределено;
ПоказатьИндикатор(Ложь);
Если Результат = Неопределено Тогда
// Задание отменено пользователем.
Возврат;
КонецЕсли;
Если Результат.Статус = "Ошибка" Тогда
СтандартныеПодсистемыКлиент.ВывестиИнформациюОбОшибке(Результат.ИнформацияОбОшибке);
Возврат;
КонецЕсли;
Итоги = ОбработатьРезультатЗагрузки(Результат.АдресРезультата);
Если Итоги.ЕстьОшибки Тогда
ПоказатьПредупреждение(,
НСтр("ru = 'Загрузка завершена с замечаниями. Подробности — в таблице ниже.'"));
Иначе
ПоказатьОповещениеПользователя(НСтр("ru = 'Загрузка чеков'"), ,
СтрШаблон(НСтр("ru = 'Обработано чеков: %1'"), Итоги.ОбработаноЧеков));
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция ОбработатьРезультатЗагрузки(Адрес)
Итоги = Новый Структура("ОбработаноЧеков, ЕстьОшибки", 0, Ложь);
Результат = ПолучитьИзВременногоХранилища(Адрес);
Если Результат = Неопределено Тогда
Возврат Итоги;
КонецЕсли;
ЗначениеВРеквизитФормы(Результат.Лог, "ЛогЗагрузки");
Итоги.ОбработаноЧеков = Результат.ОбработаноЧеков;
Итоги.ЕстьОшибки = Результат.ЕстьОшибки;
УдалитьИзВременногоХранилища(Адрес);
Возврат Итоги;
КонецФункции
&НаКлиенте
Процедура ОтменитьЗагрузку(Команда)
Если НЕ ЗначениеЗаполнено(ИдентификаторЗадания) Тогда
Возврат;
КонецЕсли;
ОтменитьЗаданиеНаСервере(ИдентификаторЗадания);
ИдентификаторЗадания = Неопределено;
ПоказатьИндикатор(Ложь);
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ОтменитьЗаданиеНаСервере(ИдентификаторЗадания)
ДлительныеОперации.ОтменитьВыполнениеЗадания(ИдентификаторЗадания);
КонецПроцедуры
&НаКлиенте
Процедура ПоказатьИндикатор(Показывать, Процент = 0, Текст = "")
Элементы.ГруппаПрогресс.Видимость = Показывать;
ПроцентВыполнения = Процент;
ТекстВыполнения = Текст;
КонецПроцедуры