Добрый день, это моя первая статья, поэтому не судите строго )
Была поставлена задача создать внешнюю обработку для переезда склада, в соответствии с требованиями, что на некоторых складах могут быть товары с определенным серийным номером, так же при переезде товаров, мы должны положить их в те же ячейки, какие были на прошлом складе, и в соответствии с этим обработка воссоздает ячейки прошлых складов, а если они уже есть, то вкладывает в них.
Все переносы я реализовал через JSON, потому что он менее объёмный и файлы получаются ниже весом, а также была реализована функция, благодаря которой мы можем скопировать права для нашего склада вести учет по серийно, со склада отправителя.
В применении обработка супер простая, заполняем все поля, выгружаем остатки со склада отправителя, после чего выдаем права нашему новоиспеченному складу на добавление серии, если мы в этом нуждаемся, и создаем перерасчет, таким образом, создается документ пересчёт товаров и товары с одного склада поступают на другой, важно учесть, что они просто копируются и создаются на новом складе.
Прилагаю код модуля формы:
#Область ПрограммныйИнтерфейс
// Выполняет запрос на наличие складских ячеек для указанного склада и возвращает результат запроса
//
// Возвращаемое значение:
// ТаблицаЗначений - Результат запроса с информацией о складских ячейках
&НаСервере
Функция ЗапросНаНаличиеЯчеек() Экспорт
Склад = ЭтотОбъект.СкладПолучатель;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СкладскиеЯчейки.Код КАК Наименование,
| СкладскиеЯчейки.Ссылка КАК Ссылка
|ИЗ
| Справочник.СкладскиеЯчейки КАК СкладскиеЯчейки
|ГДЕ
| СкладскиеЯчейки.Владелец = &Склад";
Запрос.УстановитьПараметр("Склад", Склад);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
Возврат РезультатЗапроса;
КонецФункции
#КонецОбласти
#Область ОбработчикиКомандФормы
// Инициирует процедуру выгрузки остатков на сервер
//
// Параметры:
// Команда - Неизвестно - Команда, вызывающая процедуру (детали типа не указаны)
&НаКлиенте
Процедура ВыгрузитьОстатки(Команда)
ВыгрузитьОстаткиНаСервере();
КонецПроцедуры
// Открывает диалог сохранения файла с фильтром для файлов формата JSON
//
// Параметры:
// Команда - Не определен - Команда, инициирующая процедуру сохранения файла
&НаКлиенте
Процедура СохранитьВФайл(Команда)
ДиалогВыбораФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
ДиалогВыбораФайла.Фильтр = "jsn(*.json)|*.json";
Оповещение = Новый ОписаниеОповещения("КаталогНачалоВыбораЗавершение", ЭтаФорма);
ДиалогВыбораФайла.Показать(Оповещение);
КонецПроцедуры
// Открывает диалог выбора файла для пользователя и вызывает обработчик после выбора файла
//
// Параметры:
// Команда - Команда - Команда, инициирующая открытие диалога выбора файла
&НаКлиенте
Процедура ОткрытьФайл(Команда)
ДиалогВыбора = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
ДиалогВыбора.Заголовок = "Выберите файл";
Оповещение = Новый ОписаниеОповещения("ОбработатьВыбранныйФайл", ЭтаФорма);
ДиалогВыбора.Показать(Оповещение);
КонецПроцедуры
// Вызывает процедуру проверки прав доступа к складу на сервере
//
// Параметры:
// Команда - Неопределено - Параметр команды, не используется в теле процедуры
&НаКлиенте
Процедура ПраваСклада(Команда)
ПраваСкладаНаСервере();
КонецПроцедуры
// Выполняет процедуру создания пересчета на стороне сервера
//
// Параметры:
// Команда - Не определен - Объект команды, инициировавшей выполнение процедуры
&НаКлиенте
Процедура СоздатьПересчет(Команда)
СоздатьПересчетНаСервере();
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
// Процедура выгружает остатки товаров на складе в формате JSON
&НаСервере
Процедура ВыгрузитьОстаткиНаСервере()
Остатки = "";
СкладОтправитель = ЭтотОбъект.СкладОтправитель;
МассивДанных = Новый Массив;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТоварыВЯчейкахОстатки.Номенклатура КАК Номенклатура,
| ТоварыВЯчейкахОстатки.Характеристика КАК Характеристика,
| ТоварыВЯчейкахОстатки.ВНаличииОстаток КАК Остаток,
| ТоварыВЯчейкахОстатки.Назначение КАК Назначение,
| ТоварыВЯчейкахОстатки.Серия КАК Серия,
| ТоварыВЯчейкахОстатки.Упаковка КАК Упаковка,
| ТоварыВЯчейкахОстатки.Ячейка.Код КАК ЯчейкаКод
|ИЗ
| РегистрНакопления.ТоварыВЯчейках.Остатки КАК ТоварыВЯчейкахОстатки
|ГДЕ
| ТоварыВЯчейкахОстатки.Ячейка.Владелец = &Склад";
Запрос.УстановитьПараметр("Склад", СкладОтправитель);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
Для каждого Строка из РезультатЗапроса Цикл
СтруктураНоменклатуры = Новый Структура("Номенклатура,Остаток,Характеристика,Назначение,Серия,ЯчейкаКод,Упаковка");
СтруктураНоменклатуры.Остаток = Строка.Остаток;
СтруктураНоменклатуры.ЯчейкаКод = Строка.ЯчейкаКод;
ГУИДУпаковки = Строка.Упаковка.УникальныйИдентификатор();
СтруктураНоменклатуры.Упаковка = Строка(ГУИДУпаковки);
ГУИДНоменклатура = Строка.Номенклатура.УникальныйИдентификатор();
СтруктураНоменклатуры.Номенклатура = Строка(ГУИДНоменклатура);
ГУИДХарактеристика = Строка.Характеристика.УникальныйИдентификатор();
СтруктураНоменклатуры.Характеристика = Строка(ГУИДХарактеристика);
ГУИДНазначение = Строка.Назначение.УникальныйИдентификатор();
СтруктураНоменклатуры.Назначение = Строка(ГУИДНазначение);
ГУИДСерии = Строка.Серия.УникальныйИдентификатор();
СтруктураНоменклатуры.Серия = Строка(ГУИДСерии);
МассивДанных.Добавить(СтруктураНоменклатуры);
КонецЦикла;
//Запись в формат Жсон
ПараметрыJSON = Новый ПараметрыЗаписиJSON(, Символы.Таб);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
ЗаписатьJSON(ЗаписьJSON, МассивДанных, Новый НастройкиСериализацииJSON);
Остатки = ЗаписьJSON.Закрыть();
КонецПроцедуры
// Процедура сохраняет данные в формате JSON в файл, указанный в параметрах, или выводит сообщение об ошибке, если файл не указан.
//
// Параметры:
// Результат - Массив - Массив, содержащий путь к файлу для сохранения данных
// ДополнительныеПараметры - Не определен - Дополнительные параметры, которые могут быть переданы в процедуру
&НаКлиенте
Процедура КаталогНачалоВыбораЗавершение(Результат, ДополнительныеПараметры) Экспорт
Если ЗначениеЗаполнено(Результат) тогда
СтрокаJSON = ЭтотОбъект.Остатки;
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.ОткрытьФайл(Результат[0]);
ЗаписатьJSON(ЗаписьJSON,СтрокаJSON);
ЗаписьJSON.Закрыть();
Иначе
Сообщить("Не заполнено название файла для сохранения");
КонецЕсли;
КонецПроцедуры
// Обрабатывает выбранный файл, проверяет его формат и считывает данные, если файл имеет формат JSON.
//
// Параметры:
// Результат - Массив - Массив с информацией о выбранном файле, где первый элемент - имя файла
// ДополнительныеПараметры - Неизвестно - Дополнительные параметры, передаваемые в процедуру (не используются в коде)
&НаКлиенте
Процедура ОбработатьВыбранныйФайл(Результат, ДополнительныеПараметры) Экспорт
Если ЗначениеЗаполнено(Результат) тогда
ИмяФайла = Результат[0];
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.ОткрытьФайл(ИмяФайла);
Если Прав(ИмяФайла,5) = ".json" Тогда
МассивJSON = ПрочитатьJSON(ЧтениеJSON, Ложь);
ЭтотОбъект.Остатки = ЧтениеJSON.ТекущееЗначение;
ЧтениеJSON.Закрыть();
Иначе
Сообщить("Файл должен быть типа JSON");
КонецЕсли;
Иначе
Сообщить("Не выбран файл для импорта данных");
КонецЕсли;
КонецПроцедуры
// Процедура обновляет политики учета серий для номенклатуры на складе-отправителе, основываясь на данных из регистра накопления 'ТоварыВЯчейках.Остатки'.
&НаСервере
Процедура ПраваСкладаНаСервере()
Склад = ЭтотОбъект.СкладПолучатель;
СкладОтправителя = ЭтотОбъект.СкладОтправитель;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| ТоварыВЯчейкахОстатки.Номенклатура.ВидНоменклатуры КАК НоменклатураВидНоменклатуры
|ИЗ
| РегистрНакопления.ТоварыВЯчейках.Остатки КАК ТоварыВЯчейкахОстатки
|ГДЕ
| ТоварыВЯчейкахОстатки.Ячейка.Владелец = &Склад";
Запрос.УстановитьПараметр("Склад", СкладОтправителя);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
Для каждого Строка из РезультатЗапроса Цикл
ОбъектИзменений = Строка.НоменклатураВидНоменклатуры.ПолучитьОбъект();
ПолитикиСерий = ОбъектИзменений.ПолитикиУчетаСерий;
ПараметрыПоиска = новый Структура("Склад",Склад);
МассивСтрок = ПолитикиСерий.НайтиСтроки(ПараметрыПоиска);
Если ЗначениеЗаполнено(МассивСтрок) Тогда
Для каждого стрМасс из МассивСтрок Цикл
УидПолитики = Новый УникальныйИдентификатор("7d65724d-e46c-11ef-bb9c-000c29bdb42c");
Политика = Справочники.ПолитикиУчетаСерий.ПолучитьСсылку(УидПолитики);
стрМасс.ПолитикаУчетаСерий = Политика;
КонецЦикла;
КонецЕсли;
ОбъектИзменений.Записать();
КонецЦикла;
КонецПроцедуры
// Процедура создает и проводит документ пересчета товаров, загружает фактические остатки и обновляет статусы документа.
&НаСервере
Процедура СоздатьПересчетНаСервере()
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(ЭтотОбъект.Остатки);
МассивJSON = ПрочитатьJSON(Чтение, Ложь);
МассивУчётаФакт = Новый Массив;
НовДок = ЗаполнениеТЧДокумента(МассивJSON);
МассивУчёта = Новый Массив;
Для Каждого Строка Из МассивJSON Цикл
МассивУчётаФакт.Добавить(Строка.Остаток);
МассивУчёта.Добавить(0);
КонецЦикла;
// ЗАПИСЬ ДОКУМЕНТА
НовДок.Статус = Перечисления.СтатусыПересчетовТоваров.Подготовлено;
НовДок.Записать(РежимЗаписиДокумента.Проведение);
НовДок.Статус = Перечисления.СтатусыПересчетовТоваров.ВРаботе;
НовДок.Записать(РежимЗаписиДокумента.Проведение);
// ВНЕСЕНИЕ РЕЗУЛЬТАТОВ
НовДок.Статус = Перечисления.СтатусыПересчетовТоваров.ВнесениеРезультатов;
НовДок.Товары.ЗагрузитьКолонку(МассивУчётаФакт,"КоличествоУпаковокФакт");
НовДок.Товары.ЗагрузитьКолонку(МассивУчётаФакт,"КоличествоФакт");
НовДок.Товары.ЗагрузитьКолонку(МассивУчёта,"Количество");
НовДок.Товары.ЗагрузитьКолонку(МассивУчёта,"КоличествоУпаковок");
КэшированиеЗначений = Неопределено;
СтруктураДействий = Новый Структура;
СтруктураДействий.Вставить("ПересчитатьКоличествоЕдиницСуффикс", "Факт");
ТЧКол = НовДок.Товары;
Для каждого ТекущаяСтрока Из ТЧКол Цикл
ОбработкаТабличнойЧастиСервер.ОбработатьСтрокуТЧ(ТекущаяСтрока,СтруктураДействий,КэшированиеЗначений)
КонецЦикла;
НовДок.Записать(РежимЗаписиДокумента.Проведение);
НовДок.Статус = Перечисления.СтатусыПересчетовТоваров.Выполнено;
НовДок.Записать(РежимЗаписиДокумента.Проведение);
КонецПроцедуры
// Метод предназначен для заполнения табличной части документа 'ПересчетТоваров' на основе данных, переданных в формате JSON. Метод также выполняет поиск или создание складских ячеек, если они отсутствуют.
//
// Параметры:
// МассивJSON - Массив - Массив данных в формате JSON, содержащий информацию о номенклатуре, характеристиках, назначении, упаковке, серии и ячейках.
//
// Возвращаемое значение:
// Документ.ПересчетТоваров - Созданный и заполненный документ 'ПересчетТоваров'.
&НаСервере
Функция ЗаполнениеТЧДокумента(МассивJSON)
Склад = ЭтотОбъект.СкладПолучатель;
НовДок = Документы.ПересчетТоваров.СоздатьДокумент();
НовДок.Ответственный = ЭтотОбъект.Пользователь;
НовДок.Склад = Склад;
НовДок.Дата = ТекущаяДата();
ТЗЯчеек = ЗапросНаНаличиеЯчеек();
Для Каждого Строка Из МассивJSON Цикл
// РАСШИФРОВКА JSON
ГУИДХарактеристики = Новый УникальныйИдентификатор(Строка.Характеристика);
Характеристика = Справочники.ХарактеристикиНоменклатуры.ПолучитьСсылку(ГУИДХарактеристики);
ГУИДНазначение = Новый УникальныйИдентификатор(Строка.Назначение);
Назначение = Справочники.Назначения.ПолучитьСсылку(ГУИДНазначение);
ГУИДУпаковки = Новый УникальныйИдентификатор(Строка.Упаковка);
Упаковки = Справочники.УпаковкиЕдиницыИзмерения.ПолучитьСсылку(ГУИДУпаковки);
ГУИДСерии = Новый УникальныйИдентификатор(Строка.Серия);
Серия = Справочники.СерииНоменклатуры.ПолучитьСсылку(ГУИДСерии);
ГУИДНоменклатуры = Новый УникальныйИдентификатор(Строка.Номенклатура);
Номенклатура = Справочники.Номенклатура.ПолучитьСсылку(ГУИДНоменклатуры);
// ЗАПОЛНЕНИЕ ТЧ ДОКУМЕНТА
ТЧДок = НовДок.Товары.Добавить();
ТЧДок.Номенклатура = Номенклатура;
ТЧДОК.Назначение = Назначение;
ТЧДок.Характеристика = Характеристика;
ТЧДок.СтатусУказанияСерий = 8;
ТЧДок.Серия = Серия;
ТЧДок.Упаковка = Упаковки;
// ПОИСК ЯЧЕЙКИ
СтруктураПоиска = Новый Структура("Наименование",Строка.ЯчейкаКод);
МассивПоиска = ТЗЯчеек.НайтиСтроки(СтруктураПоиска);
Если МассивПоиска.Количество() > 0 Тогда
Для каждого СтрокаПоиска из МассивПоиска Цикл
ТЧДок.Ячейка = СтрокаПоиска.Ссылка;
КонецЦикла;
Иначе
НоваяЯчейка = Справочники.СкладскиеЯчейки.СоздатьЭлемент();
НоваяЯчейка.Код = Строка.ЯчейкаКод;
НоваяЯчейка.Владелец = Склад;
НоваяЯчейка.Записать();
ТЧДок.Ячейка = НоваяЯчейка.Ссылка;
ТЗЯчеек = ЗапросНаНаличиеЯчеек();
КонецЕсли;
КонецЦикла;
Возврат НовДок;
КонецФункции
#КонецОбласти
Проверено на следующих конфигурациях и релизах:
- 1С:ERP Управление предприятием 2, релизы 2.4.12.71