TSDZakazScladVasilek/CommonTemplates/КодSetDocУТ11/Ext/Template.txt

1134 lines
55 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// =============================================================================
// УТ11: единый приём setDoc от ТСД
// — ЗаказКлиента: ТЧ КодыМаркировки + Серии/Партии
// — ПоступлениеТоваровУслуг: Марки + Серии/Партии
//
// Вставьте ВЕСЬ этот файл в модуль веб-сервиса tsdsync (или общий модуль)
// и сделайте операцию setDoc:
//
// Функция setDoc(doc) Экспорт
// Возврат ЗагрузитьДокументИзТСД(doc);
// КонецФункции
// =============================================================================
Функция setDoc(doc) Экспорт
Возврат ЗагрузитьДокументИзТСД(doc);
КонецФункции
// Точка входа: определяет тип документа и загружает данные с ТСД.
//
Функция ЗагрузитьДокументИзТСД(doc) Экспорт
Контекст = РазобратьДокументSetDoc(doc);
Если Не ЗначениеЗаполнено(Контекст.ТипДокумента) Тогда
ВызватьИсключение "setDoc: не удалось определить тип документа (заказ / поступление).";
КонецЕсли;
Если Контекст.ТипДокумента = "ПоступлениеТоваровУслуг" Тогда
Возврат ЗагрузитьПоступлениеИзТСД(Контекст.ДокументXDTO, Контекст.СсылкаСтрока);
КонецЕсли;
Возврат ЗагрузитьЗаказКлиентаИзТСД(Контекст.ДокументXDTO, Контекст.СсылкаСтрока);
КонецФункции
// --- Разбор SOAP/XDTO ----------------------------------------------------------------
Функция РазобратьДокументSetDoc(doc)
Результат = Новый Структура("ТипДокумента, ДокументXDTO, СсылкаСтрока", "", Неопределено, "");
Если doc = Неопределено Тогда
Возврат Результат;
КонецЕсли;
// 0) Сам doc уже нужный тип (часто при anyType)
ТипПоИмени = ТипДокументаПоИмениXDTO(doc);
Если ЗначениеЗаполнено(ТипПоИмени) Тогда
Результат.ТипДокумента = ТипПоИмени;
Результат.ДокументXDTO = doc;
Результат.СсылкаСтрока = СсылкаДокументаИзXDTO(doc);
Возврат Результат;
КонецЕсли;
// 1) Ищем вложенный узел по имени свойства (обход Свойства — надёжнее, чем doc["Документ.XXX"])
УзелПоступления = НайтиУзелДокументаXDTO(doc, Истина);
Если УзелПоступления <> Неопределено Тогда
Результат.ТипДокумента = "ПоступлениеТоваровУслуг";
Результат.ДокументXDTO = УзелПоступления;
Результат.СсылкаСтрока = СсылкаДокументаИзXDTO(УзелПоступления);
Возврат Результат;
КонецЕсли;
УзелЗаказа = НайтиУзелДокументаXDTO(doc, Ложь);
Если УзелЗаказа <> Неопределено Тогда
Результат.ТипДокумента = "ЗаказКлиента";
Результат.ДокументXDTO = УзелЗаказа;
Результат.СсылкаСтрока = СсылкаДокументаИзXDTO(УзелЗаказа);
Возврат Результат;
КонецЕсли;
// 2) Плоский пакет ТСД: КлючевыеСвойства сразу в doc (старый ШаблонSetDoc заказа)
Если СвойствоXDTOДок(doc, "КлючевыеСвойства") <> Неопределено Тогда
Результат.ДокументXDTO = doc;
Результат.СсылкаСтрока = СсылкаДокументаИзXDTO(doc);
Результат.ТипДокумента = ОпределитьТипПоСсылкеТСД(Результат.СсылкаСтрока, doc);
Возврат Результат;
КонецЕсли;
Возврат Результат;
КонецФункции
// Ищет вложенный документ среди свойств XDTO.
// ДляПоступления = Истина → Поступление*; Ложь → ЗаказКлиента.
//
Функция НайтиУзелДокументаXDTO(КорневойXDTO, ДляПоступления)
Если КорневойXDTO = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Попытка
КоллекцияСвойств = КорневойXDTO.Свойства();
Исключение
Возврат Неопределено;
КонецПопытки;
Для Каждого Свойство Из КоллекцияСвойств Цикл
Имя = ВРег(Строка(Свойство.Имя));
ЭтоПоступление = (СтрНайти(Имя, "ПОСТУПЛЕНИЕ") > 0);
ЭтоЗаказ = (СтрНайти(Имя, "ЗАКАЗКЛИЕНТА") > 0) Или (СтрНайти(Имя, "ЗАКАЗ_КЛИЕНТА") > 0);
Если ДляПоступления И Не ЭтоПоступление Тогда
Продолжить;
КонецЕсли;
Если Не ДляПоступления И Не ЭтоЗаказ Тогда
Продолжить;
КонецЕсли;
Попытка
Значение = КорневойXDTO.Получить(Свойство);
Исключение
Попытка
Значение = КорневойXDTO[Свойство.Имя];
Исключение
Значение = Неопределено;
КонецПопытки;
КонецПопытки;
Если Значение <> Неопределено Тогда
Возврат Значение;
КонецЕсли;
КонецЦикла;
// Запасной вариант: прямые имена, как в шаблонах ТСД
Если ДляПоступления Тогда
Узел = СвойствоXDTOДок(КорневойXDTO, "Документ.ПоступлениеТоваровУслуг");
Если Узел = Неопределено Тогда
Узел = СвойствоXDTOДок(КорневойXDTO, "Документ.ПоступлениеТоваровИУслуг");
КонецЕсли;
Если Узел = Неопределено Тогда
Узел = СвойствоXDTOДок(КорневойXDTO, "ПоступлениеТоваровУслуг");
КонецЕсли;
Если Узел = Неопределено Тогда
Узел = СвойствоXDTOДок(КорневойXDTO, "ПоступлениеТоваровИУслуг");
КонецЕсли;
Возврат Узел;
КонецЕсли;
Узел = СвойствоXDTOДок(КорневойXDTO, "Документ.ЗаказКлиента");
Если Узел = Неопределено Тогда
Узел = СвойствоXDTOДок(КорневойXDTO, "ЗаказКлиента");
КонецЕсли;
Возврат Узел;
КонецФункции
Функция ТипДокументаПоИмениXDTO(ОбъектXDTO)
ИмяТипа = "";
Попытка
ИмяТипа = Строка(ОбъектXDTO.Тип().Имя);
Исключение
Возврат "";
КонецПопытки;
ИмяВРег = ВРег(ИмяТипа);
Если СтрНайти(ИмяВРег, "ПОСТУПЛЕНИЕ") > 0 Тогда
Возврат "ПоступлениеТоваровУслуг";
ИначеЕсли СтрНайти(ИмяВРег, "ЗАКАЗКЛИЕНТА") > 0 Тогда
Возврат "ЗаказКлиента";
КонецЕсли;
Возврат "";
КонецФункции
Функция ОпределитьТипПоСсылкеТСД(СсылкаСтрока, ДокументXDTO)
Если Не ЗначениеЗаполнено(СсылкаСтрока) Тогда
Возврат "";
КонецЕсли;
// Сначала ищем существующий документ по GUID (заказ и поступление равноправны).
// Узел Серии есть и у заказа, и у поступления — по нему тип не определяем.
Попытка
СсылкаЗаказа = Документы.ЗаказКлиента.ПолучитьСсылку(
Новый УникальныйИдентификатор(СсылкаСтрока));
Если СсылкаЗаказа.ПолучитьОбъект() <> Неопределено Тогда
Возврат "ЗаказКлиента";
КонецЕсли;
Исключение
КонецПопытки;
Попытка
МенеджерПоступления = МенеджерДокументаПоступленияУТ11();
Если МенеджерПоступления <> Неопределено Тогда
СсылкаПоступления = МенеджерПоступления.ПолучитьСсылку(
Новый УникальныйИдентификатор(СсылкаСтрока));
Если СсылкаПоступления.ПолучитьОбъект() <> Неопределено Тогда
Возврат "ПоступлениеТоваровУслуг";
КонецЕсли;
КонецЕсли;
Исключение
КонецПопытки;
// По умолчанию — заказ (исторический формат ТСД / плоский ШаблонSetDoc)
Возврат "ЗаказКлиента";
КонецФункции
Функция СсылкаДокументаИзXDTO(ДокументXDTO)
КлючевыеСвойства = СвойствоXDTOДок(ДокументXDTO, "КлючевыеСвойства");
Если КлючевыеСвойства = Неопределено Тогда
Возврат "";
КонецЕсли;
Ссылка = СвойствоXDTOДок(КлючевыеСвойства, "Ссылка");
Если Ссылка = Неопределено Тогда
Ссылка = СвойствоXDTOДок(КлючевыеСвойства, "ссылка");
КонецЕсли;
Возврат СокрЛП(Строка(Ссылка));
КонецФункции
// --- Заказ клиента -------------------------------------------------------------------
Функция ЗагрузитьЗаказКлиентаИзТСД(xmldoc, СсылкаСтрока = "") Экспорт
Если Не ЗначениеЗаполнено(СсылкаСтрока) Тогда
СсылкаСтрока = СсылкаДокументаИзXDTO(xmldoc);
КонецЕсли;
Если Не ЗначениеЗаполнено(СсылкаСтрока) Тогда
Возврат Ложь;
КонецЕсли;
ЗаказСсылка = Документы.ЗаказКлиента.ПолучитьСсылку(Новый УникальныйИдентификатор(СсылкаСтрока));
ЗаказКлиента = ЗаказСсылка.ПолучитьОбъект();
Если ЗаказКлиента = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
ЗаполнитьКодыМаркировкиДокументаИзТСД(ЗаказКлиента, xmldoc);
ЗагрузитьПартииПоступленияИзТСД(ЗаказКлиента, xmldoc);
ЗаписатьДокументИзТСД(ЗаказКлиента);
Возврат Истина;
КонецФункции
// --- Поступление ----------------------------------------------------------------------
// В УТ11 документ может называться ПоступлениеТоваровУслуг или ПриобретениеТоваровУслуг.
//
Функция МенеджерДокументаПоступленияУТ11()
Если Метаданные.Документы.Найти("ПоступлениеТоваровУслуг") <> Неопределено Тогда
Возврат Документы.ПоступлениеТоваровУслуг;
КонецЕсли;
Если Метаданные.Документы.Найти("ПриобретениеТоваровУслуг") <> Неопределено Тогда
Возврат Документы.ПриобретениеТоваровУслуг;
КонецЕсли;
Возврат Неопределено;
КонецФункции
Функция ИмяДокументаПоступленияУТ11()
Если Метаданные.Документы.Найти("ПоступлениеТоваровУслуг") <> Неопределено Тогда
Возврат "ПоступлениеТоваровУслуг";
КонецЕсли;
Если Метаданные.Документы.Найти("ПриобретениеТоваровУслуг") <> Неопределено Тогда
Возврат "ПриобретениеТоваровУслуг";
КонецЕсли;
Возврат "ПоступлениеТоваровУслуг";
КонецФункции
Функция ЗагрузитьПоступлениеИзТСД(xmldoc, СсылкаСтрока = "") Экспорт
Если Не ЗначениеЗаполнено(СсылкаСтрока) Тогда
СсылкаСтрока = СсылкаДокументаИзXDTO(xmldoc);
КонецЕсли;
Менеджер = МенеджерДокументаПоступленияУТ11();
Если Менеджер = Неопределено Тогда
ВызватьИсключение "setDoc: в УТ11 нет документа поступления (Поступление/ПриобретениеТоваровУслуг).";
КонецЕсли;
Поступление = Неопределено;
Если ЗначениеЗаполнено(СсылкаСтрока) Тогда
ПоступлениеСсылка = Менеджер.ПолучитьСсылку(
Новый УникальныйИдентификатор(СсылкаСтрока));
Поступление = ПоступлениеСсылка.ПолучитьОбъект();
КонецЕсли;
Если Поступление = Неопределено Тогда
Поступление = НайтиПоступлениеУТ11ПоНомеруИзXDTO(xmldoc);
КонецЕсли;
Если Поступление = Неопределено Тогда
ВызватьИсключение "setDoc: поступление не найдено в УТ11 по ссылке "
+ СсылкаСтрока + " и по номеру.";
КонецЕсли;
ЗаполнитьКодыМаркировкиДокументаИзТСД(Поступление, xmldoc);
ЗагрузитьПартииПоступленияИзТСД(Поступление, xmldoc);
ЗаполнитьОтсканированоПоступленияИзТСД(Поступление, xmldoc);
ЗаполнитьКомментарийПоступленияИзТСД(Поступление, xmldoc);
ЗаписатьДокументИзТСД(Поступление);
Возврат Истина;
КонецФункции
Функция НайтиПоступлениеУТ11ПоНомеруИзXDTO(xmldoc)
Номер = "";
Попытка
Номер = СокрЛП(Строка(xmldoc.КлючевыеСвойства.Номер));
Исключение
Номер = "";
КонецПопытки;
Если Не ЗначениеЗаполнено(Номер) Тогда
Возврат Неопределено;
КонецЕсли;
ИмяДок = ИмяДокументаПоступленияУТ11();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Док.Ссылка КАК Ссылка
|ИЗ
| Документ." + ИмяДок + " КАК Док
|ГДЕ
| Док.Номер = &Номер
| И НЕ Док.ПометкаУдаления
|
|УПОРЯДОЧИТЬ ПО
| Док.Дата УБЫВ";
Запрос.УстановитьПараметр("Номер", Номер);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка.ПолучитьОбъект();
КонецЕсли;
Возврат Неопределено;
КонецФункции
Процедура ЗаписатьДокументИзТСД(ДокОбъект)
Если ДокОбъект.Проведен Тогда
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
Иначе
ДокОбъект.Записать();
КонецЕсли;
КонецПроцедуры
// Дописывает комментарий с ТСД в реквизит Комментарий поступления.
// Если комментарий в УТ11 уже есть — перевод строки + пометка «из ТСД» + текст с ТСД.
//
Процедура ЗаполнитьКомментарийПоступленияИзТСД(Поступление, xmldoc) Экспорт
Если Поступление = Неопределено Или xmldoc = Неопределено Тогда
Возврат;
КонецЕсли;
КомментарийТСД = "";
Попытка
КомментарийТСД = СокрЛП(Строка(xmldoc.Комментарий));
Исключение
КомментарийТСД = "";
КонецПопытки;
Если Не ЗначениеЗаполнено(КомментарийТСД) Тогда
Возврат;
КонецЕсли;
ТекстИзТСД = "Комментарий из ТСД: " + КомментарийТСД;
КомментарийУТ = СокрЛП(Строка(Поступление.Комментарий));
Если ЗначениеЗаполнено(КомментарийУТ) Тогда
Поступление.Комментарий = КомментарийУТ + Символы.ПС + ТекстИзТСД;
Иначе
Поступление.Комментарий = ТекстИзТСД;
КонецЕсли;
КонецПроцедуры
// Заполнение ТЧ Товары.Отсканировано при приёме поступления с ТСД.
// Вызывать ПОСЛЕ ЗагрузитьПартииПоступленияИзТСД.
//
Процедура ЗаполнитьОтсканированоПоступленияИзТСД(Поступление, xmldoc) Экспорт
ИмяРеквизита = ИмяРеквизитаОтсканированоТоваров(Поступление);
Если Не ЗначениеЗаполнено(ИмяРеквизита) Тогда
Возврат;
КонецЕсли;
Для Каждого СтрокаТовара Из Поступление.Товары Цикл
СтрокаТовара[ИмяРеквизита] = 0;
КонецЦикла;
// 1) Явное значение из узла Товары пакета ТСД
УзелТоваров = СвойствоXDTOДок(xmldoc, "Товары");
Если УзелТоваров <> Неопределено Тогда
Для Каждого СтрокаXDTO Из СтрокиXDTO(УзелТоваров, "Строка") Цикл
Отсканировано = ЧислоСвойстваXDTO(СтрокаXDTO, "Отсканировано");
Если Отсканировано = 0 Тогда
Продолжить;
КонецЕсли;
СтрокаТовара = НайтиСтрокуТоваровПоступленияИзXDTO(Поступление, СтрокаXDTO);
Если СтрокаТовара <> Неопределено Тогда
СтрокаТовара[ИмяРеквизита] = Отсканировано;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ЕстьЗаполненноеОтсканировано(Поступление, ИмяРеквизита) Тогда
Возврат;
КонецЕсли;
// 2) Сумма по уже загруженной ТЧ Партии документа
Если Поступление.Метаданные().ТабличныеЧасти.Найти("Партии") <> Неопределено
И Поступление.Партии.Количество() > 0 Тогда
Итоги = Новый Соответствие;
Для Каждого СтрокаПартии Из Поступление.Партии Цикл
Если Не ЗначениеЗаполнено(СтрокаПартии.Номенклатура) Тогда
Продолжить;
КонецЕсли;
Кол = 0;
Попытка
Кол = Число(СтрокаПартии.КоличествоВПартии);
Исключение
Кол = 1;
КонецПопытки;
Если Кол = 0 Тогда
Кол = 1;
КонецЕсли;
Было = Итоги.Получить(СтрокаПартии.Номенклатура);
Итоги.Вставить(СтрокаПартии.Номенклатура, ?(Было = Неопределено, 0, Было) + Кол);
КонецЦикла;
Для Каждого КлючИЗначение Из Итоги Цикл
Найденные = Поступление.Товары.НайтиСтроки(Новый Структура("Номенклатура", КлючИЗначение.Ключ));
Если Найденные.Количество() > 0 Тогда
Найденные[0][ИмяРеквизита] = КлючИЗначение.Значение;
КонецЕсли;
КонецЦикла;
Если ЕстьЗаполненноеОтсканировано(Поступление, ИмяРеквизита) Тогда
Возврат;
КонецЕсли;
КонецЕсли;
// 3) Сумма по узлу Серии из пакета
УзелСерий = СвойствоXDTOДок(xmldoc, "Серии");
Если УзелСерий = Неопределено Тогда
Возврат;
КонецЕсли;
Итоги = Новый Соответствие;
Для Каждого Строка Из СтрокиXDTO(УзелСерий, "Строка") Цикл
НоменклатураСсылка = НоменклатураИзСтрокиПоступленияXDTO(Строка);
Если Не ЗначениеЗаполнено(НоменклатураСсылка) Тогда
Продолжить;
КонецЕсли;
Кол = ЧислоСвойстваXDTO(Строка, "Количество");
Если Кол = 0 Тогда
Кол = 1;
КонецЕсли;
Было = Итоги.Получить(НоменклатураСсылка);
Итоги.Вставить(НоменклатураСсылка, ?(Было = Неопределено, 0, Было) + Кол);
КонецЦикла;
Для Каждого КлючИЗначение Из Итоги Цикл
Найденные = Поступление.Товары.НайтиСтроки(Новый Структура("Номенклатура", КлючИЗначение.Ключ));
Если Найденные.Количество() > 0 Тогда
Найденные[0][ИмяРеквизита] = КлючИЗначение.Значение;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ИмяРеквизитаОтсканированоТоваров(Поступление)
Если Поступление.Метаданные().ТабличныеЧасти.Найти("Товары") = Неопределено Тогда
Возврат "";
КонецЕсли;
Реквизиты = Поступление.Метаданные().ТабличныеЧасти.Товары.Реквизиты;
Если Реквизиты.Найти("Отсканировано") <> Неопределено Тогда
Возврат "Отсканировано";
КонецЕсли;
Если Реквизиты.Найти("отсканировано") <> Неопределено Тогда
Возврат "отсканировано";
КонецЕсли;
Возврат "";
КонецФункции
Функция ЕстьЗаполненноеОтсканировано(Поступление, ИмяРеквизита)
Для Каждого СтрокаТовара Из Поступление.Товары Цикл
Если СтрокаТовара[ИмяРеквизита] <> 0 Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
Функция ЧислоСвойстваXDTO(ОбъектXDTO, ИмяСвойства)
Значение = СвойствоXDTOДок(ОбъектXDTO, ИмяСвойства);
Если Значение = Неопределено Или Не ЗначениеЗаполнено(Значение) Тогда
Возврат 0;
КонецЕсли;
Попытка
Возврат Число(Значение);
Исключение
Возврат 0;
КонецПопытки;
КонецФункции
Функция НайтиСтрокуТоваровПоступленияИзXDTO(Поступление, СтрокаXDTO)
НомерСтроки = СвойствоXDTOДок(СтрокаXDTO, "НомерСтрокиДокумента");
Если НомерСтроки = Неопределено Тогда
НомерСтроки = СвойствоXDTOДок(СтрокаXDTO, "КодСтроки");
КонецЕсли;
Если НомерСтроки = Неопределено Тогда
НомерСтроки = СвойствоXDTOДок(СтрокаXDTO, "КлючСвязи");
КонецЕсли;
Если НомерСтроки <> Неопределено Тогда
Попытка
Ном = Число(НомерСтроки);
Если Ном > 0 И Ном <= Поступление.Товары.Количество() Тогда
Возврат Поступление.Товары[Ном - 1];
КонецЕсли;
Исключение
КонецПопытки;
КонецЕсли;
НоменклатураСсылка = НоменклатураИзСтрокиПоступленияXDTO(СтрокаXDTO);
Если Не ЗначениеЗаполнено(НоменклатураСсылка) Тогда
Возврат Неопределено;
КонецЕсли;
Найденные = Поступление.Товары.НайтиСтроки(Новый Структура("Номенклатура", НоменклатураСсылка));
Если Найденные.Количество() > 0 Тогда
Возврат Найденные[0];
КонецЕсли;
Возврат Неопределено;
КонецФункции
Функция НоменклатураИзСтрокиПоступленияXDTO(СтрокаXDTO)
Попытка
СсылкаСтрока = Строка(СтрокаXDTO.ДанныеНоменклатуры.Номенклатура.Ссылка);
Возврат Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(СсылкаСтрока));
Исключение
КонецПопытки;
Попытка
СсылкаСтрока = Строка(СтрокаXDTO.Номенклатура.Ссылка);
Возврат Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(СсылкаСтрока));
Исключение
КонецПопытки;
Возврат Справочники.Номенклатура.ПустаяСсылка();
КонецФункции
// Общая загрузка марок в ТЧ документа (заказ или поступление).
//
Процедура ЗаполнитьКодыМаркировкиДокументаИзТСД(ДокОбъект, xmldoc)
ИмяТЧМарок = ИмяТЧМарокДокумента(ДокОбъект);
Если Не ЗначениеЗаполнено(ИмяТЧМарок) Тогда
Возврат;
КонецЕсли;
ТЧМарок = ДокОбъект[ИмяТЧМарок];
ТЧМарок.Очистить();
УзелМарок = СвойствоXDTOДок(xmldoc, "Марки");
Если УзелМарок = Неопределено Тогда
Возврат;
КонецЕсли;
Для Каждого Строка Из СтрокиXDTO(УзелМарок, "Строка") Цикл
НоваяСтрока = ТЧМарок.Добавить();
КодМарки = ДекодироватьКодМаркиИзТСД(СвойствоXDTOДок(Строка, "Код"));
Если ИмяТЧМарок = "КодыМаркировки" Тогда
НоваяСтрока.Код = КодМарки;
НомерСтрокиДок = СвойствоXDTOДок(Строка, "НомерСтрокиДокумента");
Если НомерСтрокиДок <> Неопределено Тогда
НоваяСтрока.Строка = Число(НомерСтрокиДок);
КонецЕсли;
НоменклатураСсылка = НоменклатураИзСтрокиМаркиXDTO(Строка);
Если ЗначениеЗаполнено(НоменклатураСсылка) Тогда
НоваяСтрока.Номенклатура = НоменклатураСсылка;
КонецЕсли;
Упаковка = УпаковкаИзСтрокиМаркиXDTO(Строка);
НоваяСтрока.Упаковка = ?(ЗначениеЗаполнено(Упаковка), Упаковка, 1);
Иначе
// ШтрихкодыУпаковокТоваров / похожие ТЧ
ЗаписатьРеквизитЕслиЕсть(НоваяСтрока, "ЗначениеШтрихкода", КодМарки);
ЗаписатьРеквизитЕслиЕсть(НоваяСтрока, "Штрихкод", КодМарки);
НоменклатураСсылка = НоменклатураИзСтрокиМаркиXDTO(Строка);
Если ЗначениеЗаполнено(НоменклатураСсылка) Тогда
ЗаписатьРеквизитЕслиЕсть(НоваяСтрока, "Номенклатура", НоменклатураСсылка);
КонецЕсли;
Упаковка = УпаковкаИзСтрокиМаркиXDTO(Строка);
ЗаписатьРеквизитЕслиЕсть(НоваяСтрока, "Количество", ?(ЗначениеЗаполнено(Упаковка), Упаковка, 1));
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ИмяТЧМарокДокумента(ДокОбъект)
ТЧ = ДокОбъект.Метаданные().ТабличныеЧасти;
Если ТЧ.Найти("КодыМаркировки") <> Неопределено Тогда
Возврат "КодыМаркировки";
ИначеЕсли ТЧ.Найти("ШтрихкодыУпаковокТоваров") <> Неопределено Тогда
Возврат "ШтрихкодыУпаковокТоваров";
КонецЕсли;
Возврат "";
КонецФункции
Функция НоменклатураИзСтрокиМаркиXDTO(Строка)
Попытка
ДанныеНоменклатуры = Строка.ДанныеНоменклатуры;
СсылкаСтрока = Строка(ДанныеНоменклатуры.Номенклатура.Ссылка);
Возврат Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(СсылкаСтрока));
Исключение
Возврат Справочники.Номенклатура.ПустаяСсылка();
КонецПопытки;
КонецФункции
Функция УпаковкаИзСтрокиМаркиXDTO(Строка)
Попытка
Возврат Строка.ДанныеНоменклатуры.ВУпаковке;
Исключение
Возврат Неопределено;
КонецПопытки;
КонецФункции
// ТЧ Партии с ТСД приходят в узле Серии (ШаблонSetDocПоступлениеПартия / заказ).
// Создаём / находим СерииНоменклатуры и пишем в ТЧ Серии документа УТ11
// (заказ клиента или поступление — у кого есть ТЧ Серии/Партии).
//
Процедура ЗагрузитьПартииПоступленияИзТСД(Поступление, xmldoc) Экспорт
УзелСерий = СвойствоXDTOДок(xmldoc, "Серии");
Если УзелСерий = Неопределено Тогда
Возврат;
КонецЕсли;
СтрокиСерий = СтрокиXDTO(УзелСерий, "Строка");
Если СтрокиСерий.Количество() = 0 Тогда
Возврат;
КонецЕсли;
МетаТЧ = Поступление.Метаданные().ТабличныеЧасти;
ЕстьТЧСерии = (МетаТЧ.Найти("Серии") <> Неопределено);
ЕстьТЧПартии = (МетаТЧ.Найти("Партии") <> Неопределено);
Если Не ЕстьТЧСерии И Не ЕстьТЧПартии Тогда
Возврат;
КонецЕсли;
Если ЕстьТЧСерии Тогда
Поступление.Серии.Очистить();
КонецЕсли;
Если ЕстьТЧПартии Тогда
Поступление.Партии.Очистить();
КонецЕсли;
Для Каждого Строка Из СтрокиСерий Цикл
ПараметрыПартии = ПараметрыПартииИзСтрокиXDTO(Строка);
Если Не ЗначениеЗаполнено(ПараметрыПартии.Номенклатура) Тогда
Продолжить;
КонецЕсли;
СерияСсылка = Неопределено;
Если ЗначениеЗаполнено(ПараметрыПартии.Номер) Тогда
СерияСсылка = НайтиИлиСоздатьСериюНоменклатуры(
ПараметрыПартии.Номенклатура,
ПараметрыПартии.Номер,
ПараметрыПартии);
КонецЕсли;
Если ЕстьТЧСерии Тогда
СтрокаСерии = Поступление.Серии.Добавить();
СтрокаСерии.Номенклатура = ПараметрыПартии.Номенклатура;
СтрокаСерии.Количество = ?(ПараметрыПартии.Количество = 0, 1, ПараметрыПартии.Количество);
Если ЗначениеЗаполнено(СерияСсылка) Тогда
СтрокаСерии.Серия = СерияСсылка;
КонецЕсли;
ЗаписатьРеквизитЕслиЕсть(СтрокаСерии, "КоличествоУпаковок", СтрокаСерии.Количество);
Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Поступление, "Склад") Тогда
ЗаписатьРеквизитЕслиЕсть(СтрокаСерии, "Склад", Поступление.Склад);
КонецЕсли;
КонецЕсли;
Если ЕстьТЧПартии Тогда
СтрокаПартии = Поступление.Партии.Добавить();
ЗаполнитьСтрокуПартииИзПараметров(СтрокаПартии, ПараметрыПартии, СерияСсылка);
КонецЕсли;
КонецЦикла;
// Чтобы серии не «сбрасывались» при записи типового документа УТ11
Попытка
ПараметрыУказанияСерий = НоменклатураСервер.ПараметрыУказанияСерий(
Поступление, Поступление.Метаданные());
НоменклатураСервер.ЗаполнитьСтатусыУказанияСерий(Поступление, ПараметрыУказанияСерий);
Исключение
КонецПопытки;
КонецПроцедуры
Функция ПараметрыПартииИзСтрокиXDTO(Строка)
Результат = Новый Структура;
Результат.Вставить("Номенклатура", Справочники.Номенклатура.ПустаяСсылка());
Результат.Вставить("Номер", "");
Результат.Вставить("ДатаПроизводства", '00010101');
Результат.Вставить("ГоденДо", '00010101');
Результат.Вставить("Штрихкод", "");
Результат.Вставить("Количество", 1);
Результат.Вставить("НомерПартии", "");
Результат.Вставить("СерияПартии", "");
Попытка
Результат.Номенклатура = Справочники.Номенклатура.ПолучитьСсылку(
Новый УникальныйИдентификатор(Строка(Строка.Номенклатура.Ссылка)));
Исключение
КонецПопытки;
Попытка
Результат.Количество = Число(Строка.Количество);
Исключение
Результат.Количество = 1;
КонецПопытки;
Если Результат.Количество = 0 Тогда
Результат.Количество = 1;
КонецЕсли;
Попытка
Результат.Штрихкод = СокрЛП(Строка(Строка.Штрихкод));
Исключение
КонецПопытки;
Попытка
Результат.НомерПартии = СокрЛП(Строка(Строка.Партия));
Исключение
КонецПопытки;
Попытка
Результат.СерияПартии = СокрЛП(Строка(Строка.СерияПартии));
Исключение
КонецПопытки;
НомерИзСерии = "";
Попытка
НомерИзСерии = СокрЛП(Строка(Строка.Серия.Номер));
Исключение
КонецПопытки;
// Приоритет номера: Серия.Номер → СерияПартии → Партия
Если ЗначениеЗаполнено(НомерИзСерии) Тогда
Результат.Номер = НомерИзСерии;
ИначеЕсли ЗначениеЗаполнено(Результат.СерияПартии) Тогда
Результат.Номер = Результат.СерияПартии;
Иначе
Результат.Номер = Результат.НомерПартии;
КонецЕсли;
Попытка
Если ЗначениеЗаполнено(Строка.Серия.ДатаПроизводства) Тогда
Результат.ДатаПроизводства = XMLЗначение(Тип("Дата"), Строка(Строка.Серия.ДатаПроизводства));
КонецЕсли;
Исключение
КонецПопытки;
Попытка
Если ЗначениеЗаполнено(Строка.Серия.ГоденДо) Тогда
Результат.ГоденДо = XMLЗначение(Тип("Дата"), Строка(Строка.Серия.ГоденДо));
КонецЕсли;
Исключение
КонецПопытки;
Возврат Результат;
КонецФункции
Процедура ЗаполнитьСтрокуПартииИзПараметров(СтрокаПартии, ПараметрыПартии, СерияСсылка)
СтрокаПартии.Номенклатура = ПараметрыПартии.Номенклатура;
ЗаписатьРеквизитЕслиЕсть(СтрокаПартии, "НомерПартии", ПараметрыПартии.НомерПартии);
ЗаписатьРеквизитЕслиЕсть(СтрокаПартии, "СерияПартии",
?(ЗначениеЗаполнено(ПараметрыПартии.СерияПартии), ПараметрыПартии.СерияПартии, ПараметрыПартии.Номер));
Если ЗначениеЗаполнено(ПараметрыПартии.ДатаПроизводства) Тогда
ЗаписатьРеквизитЕслиЕсть(СтрокаПартии, "ДатаПартии", ПараметрыПартии.ДатаПроизводства);
КонецЕсли;
Если ЗначениеЗаполнено(ПараметрыПартии.ГоденДо) Тогда
ЗаписатьРеквизитЕслиЕсть(СтрокаПартии, "ГоденДо", ПараметрыПартии.ГоденДо);
КонецЕсли;
ЗаписатьРеквизитЕслиЕсть(СтрокаПартии, "ШК", ПараметрыПартии.Штрихкод);
ЗаписатьРеквизитЕслиЕсть(СтрокаПартии, "КоличествоВПартии", ПараметрыПартии.Количество);
Если ЗначениеЗаполнено(СерияСсылка) Тогда
ЗаписатьРеквизитЕслиЕсть(СтрокаПартии, "Серия", СерияСсылка);
КонецЕсли;
КонецПроцедуры
Процедура ЗаполнитьСтрокуПартииИзXDTO(СтрокаПартии, Строка)
ПараметрыПартии = ПараметрыПартииИзСтрокиXDTO(Строка);
ЗаполнитьСтрокуПартииИзПараметров(СтрокаПартии, ПараметрыПартии, Неопределено);
КонецПроцедуры
// Поиск серии по нескольким реквизитам; если не найдена — создание.
// Критерии поиска (все заполненные должны совпасть):
// 1) ВидНоменклатуры
// 2) Номер
// 3) ДатаПроизводства (если передана с ТСД)
// 4) ГоденДо (если передана с ТСД)
// 5) RFID / Штрихкод (если есть реквизит у серии и значение с ТСД)
//
Функция НайтиИлиСоздатьСериюНоменклатуры(Номенклатура, НомерСерии, ПараметрыПартии = Неопределено) Экспорт
НомерСерии = СокрЛП(Строка(НомерСерии));
Если Не ЗначениеЗаполнено(Номенклатура) Или Не ЗначениеЗаполнено(НомерСерии) Тогда
Возврат Справочники.СерииНоменклатуры.ПустаяСсылка();
КонецЕсли;
Если ПараметрыПартии = Неопределено Тогда
ПараметрыПартии = Новый Структура("ДатаПроизводства, ГоденДо, Штрихкод",
'00010101', '00010101', "");
КонецЕсли;
ВидНоменклатуры = Неопределено;
Попытка
ВидНоменклатуры = Номенклатура.ВидНоменклатуры;
Исключение
КонецПопытки;
Если Не ЗначениеЗаполнено(ВидНоменклатуры) Тогда
Возврат Справочники.СерииНоменклатуры.ПустаяСсылка();
КонецЕсли;
Найденная = НайтиСериюНоменклатурыПоРеквизитам(
ВидНоменклатуры, НомерСерии, ПараметрыПартии);
Если ЗначениеЗаполнено(Найденная) Тогда
Возврат Найденная;
КонецЕсли;
Возврат СоздатьСериюНоменклатуры(ВидНоменклатуры, НомерСерии, ПараметрыПартии, Номенклатура);
КонецФункции
Функция НайтиСериюНоменклатурыПоРеквизитам(ВидНоменклатуры, НомерСерии, ПараметрыПартии)
МетаСерии = Метаданные.Справочники.СерииНоменклатуры;
ЕстьДатаПроизводства = (МетаСерии.Реквизиты.Найти("ДатаПроизводства") <> Неопределено);
ЕстьГоденДо = (МетаСерии.Реквизиты.Найти("ГоденДо") <> Неопределено);
ЕстьRFID = (МетаСерии.Реквизиты.Найти("RFIDTID") <> Неопределено);
ЕстьНомерКиЗ = (МетаСерии.Реквизиты.Найти("НомерКиЗГИСМ") <> Неопределено);
ДатаПроизводства = '00010101';
ГоденДо = '00010101';
Штрихкод = "";
ПараметрыПартии.Свойство("ДатаПроизводства", ДатаПроизводства);
ПараметрыПартии.Свойство("ГоденДо", ГоденДо);
ПараметрыПартии.Свойство("Штрихкод", Штрихкод);
Если ДатаПроизводства = Неопределено Тогда
ДатаПроизводства = '00010101';
КонецЕсли;
Если ГоденДо = Неопределено Тогда
ГоденДо = '00010101';
КонецЕсли;
Если Штрихкод = Неопределено Тогда
Штрихкод = "";
КонецЕсли;
Штрихкод = СокрЛП(Строка(Штрихкод));
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 50
| Серии.Ссылка КАК Ссылка,
| Серии.Номер КАК Номер
|ИЗ
| Справочник.СерииНоменклатуры КАК Серии
|ГДЕ
| НЕ Серии.ПометкаУдаления
| И Серии.ВидНоменклатуры = &ВидНоменклатуры
| И Серии.Номер = &Номер";
Если ЕстьДатаПроизводства И ЗначениеЗаполнено(ДатаПроизводства) Тогда
Запрос.Текст = Запрос.Текст + "
| И Серии.ДатаПроизводства = &ДатаПроизводства";
Запрос.УстановитьПараметр("ДатаПроизводства", ДатаПроизводства);
КонецЕсли;
Если ЕстьГоденДо И ЗначениеЗаполнено(ГоденДо) Тогда
Запрос.Текст = Запрос.Текст + "
| И Серии.ГоденДо = &ГоденДо";
Запрос.УстановитьПараметр("ГоденДо", ГоденДо);
КонецЕсли;
Запрос.УстановитьПараметр("ВидНоменклатуры", ВидНоменклатуры);
Запрос.УстановитьПараметр("Номер", НомерСерии);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
СерияОбъект = Выборка.Ссылка;
// Доп. сверка по штрихкоду / RFID, если значение пришло с ТСД
Если ЗначениеЗаполнено(Штрихкод) Тогда
СовпалШК = Ложь;
Если ЕстьRFID Тогда
Попытка
Если СокрЛП(Строка(СерияОбъект.RFIDTID)) = Штрихкод Тогда
СовпалШК = Истина;
КонецЕсли;
Исключение
КонецПопытки;
КонецЕсли;
Если Не СовпалШК И ЕстьНомерКиЗ Тогда
Попытка
Если СокрЛП(Строка(СерияОбъект.НомерКиЗГИСМ)) = Штрихкод Тогда
СовпалШК = Истина;
КонецЕсли;
Исключение
КонецПопытки;
КонецЕсли;
// Если у серии нет полей под ШК — не отбрасываем кандидата
Если Не ЕстьRFID И Не ЕстьНомерКиЗ Тогда
СовпалШК = Истина;
КонецЕсли;
// ШК передан, поля есть, но не совпали — ищем дальше
Если (ЕстьRFID Или ЕстьНомерКиЗ) И Не СовпалШК Тогда
// если у найденной серии ШК пустой — считаем совпадением по номеру+виду(+датам)
ШКСерииПустой = Истина;
Если ЕстьRFID Тогда
Попытка
ШКСерииПустой = Не ЗначениеЗаполнено(СерияОбъект.RFIDTID);
Исключение
КонецПопытки;
КонецЕсли;
Если ШКСерииПустой Тогда
Возврат Выборка.Ссылка;
КонецЕсли;
Продолжить;
КонецЕсли;
КонецЕсли;
Возврат Выборка.Ссылка;
КонецЦикла;
Возврат Справочники.СерииНоменклатуры.ПустаяСсылка();
КонецФункции
Функция СоздатьСериюНоменклатуры(ВидНоменклатуры, НомерСерии, ПараметрыПартии, Номенклатура)
СерияОбъект = Справочники.СерииНоменклатуры.СоздатьЭлемент();
СерияОбъект.ВидНоменклатуры = ВидНоменклатуры;
СерияОбъект.Номер = НомерСерии;
ДатаПроизводства = '00010101';
ГоденДо = '00010101';
Штрихкод = "";
ПараметрыПартии.Свойство("ДатаПроизводства", ДатаПроизводства);
ПараметрыПартии.Свойство("ГоденДо", ГоденДо);
ПараметрыПартии.Свойство("Штрихкод", Штрихкод);
Если ЗначениеЗаполнено(ДатаПроизводства) Тогда
ЗаписатьРеквизитЕслиЕсть(СерияОбъект, "ДатаПроизводства", ДатаПроизводства);
КонецЕсли;
Если ЗначениеЗаполнено(ГоденДо) Тогда
ЗаписатьРеквизитЕслиЕсть(СерияОбъект, "ГоденДо", ГоденДо);
КонецЕсли;
Если ЗначениеЗаполнено(Штрихкод) Тогда
ЗаписатьРеквизитЕслиЕсть(СерияОбъект, "RFIDTID", Штрихкод);
ЗаписатьРеквизитЕслиЕсть(СерияОбъект, "НомерКиЗГИСМ", Штрихкод);
КонецЕсли;
// Наименование — часто заполняется номером
Попытка
Если Не ЗначениеЗаполнено(СерияОбъект.Наименование) Тогда
СерияОбъект.Наименование = НомерСерии;
КонецЕсли;
Исключение
КонецПопытки;
Попытка
СерияОбъект.Записать();
Возврат СерияОбъект.Ссылка;
Исключение
Возврат Справочники.СерииНоменклатуры.ПустаяСсылка();
КонецПопытки;
КонецФункции
// --- Общие помощники -----------------------------------------------------------------
Функция ДекодироватьКодМаркиИзТСД(Знач КодИзXML)
Исходная = СокрЛП(Строка(КодИзXML));
Если Не ЗначениеЗаполнено(Исходная) Тогда
Возврат "";
КонецЕсли;
Если СтрНачинаетсяС(Исходная, "01") Или СтрНайти(Исходная, Символ(29)) > 0 Тогда
Возврат Исходная;
КонецЕсли;
Попытка
ДвоичныеДанные = Base64Значение(Исходная);
Если ДвоичныеДанные = Неопределено Тогда
Возврат Исходная;
КонецЕсли;
Чтение = Новый ЧтениеДанных(ДвоичныеДанные);
Декодированная = СокрЛП(Чтение.ПрочитатьСимволы());
Чтение.Закрыть();
Если ЗначениеЗаполнено(Декодированная) Тогда
Возврат Декодированная;
КонецЕсли;
Исключение
КонецПопытки;
Возврат Исходная;
КонецФункции
Функция СтрокиXDTO(УзелТаблицы, ИмяСтроки = "Строка")
Результат = Новый Массив;
Если УзелТаблицы = Неопределено Тогда
Возврат Результат;
КонецЕсли;
Попытка
ЗначениеСтрок = УзелТаблицы[ИмяСтроки];
Исключение
Возврат Результат;
КонецПопытки;
Если ТипЗнч(ЗначениеСтрок) = Тип("СписокXDTO") Тогда
Для Каждого Элемент Из ЗначениеСтрок Цикл
Результат.Добавить(Элемент);
КонецЦикла;
ИначеЕсли ЗначениеСтрок <> Неопределено Тогда
Результат.Добавить(ЗначениеСтрок);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция СвойствоXDTOДок(ОбъектXDTO, ИмяСвойства)
Если ОбъектXDTO = Неопределено Или Не ЗначениеЗаполнено(ИмяСвойства) Тогда
Возврат Неопределено;
КонецЕсли;
Попытка
Возврат ОбъектXDTO[ИмяСвойства];
Исключение
Возврат Неопределено;
КонецПопытки;
КонецФункции
Процедура ЗаписатьРеквизитЕслиЕсть(СтрокаТЧ, ИмяРеквизита, Значение)
Попытка
СтрокаТЧ[ИмяРеквизита] = Значение;
Исключение
КонецПопытки;
КонецПроцедуры