Смена контрагента в реализации. УТ 11.4
Клиент поставил задачу — при смене контрагента в реализации, чтобы изменялся контрагент и в заказе. При этом нужно отключить очистку табличной части товаров, которая происходит сейчас при смене контрагента в реализации.
Учитывая сложности с партнерами-контрагентами, проверил, какая процедура вызывается отладчиком:
Нашел место, где очищаются товары:
К сожалению, расширением сюда не подлезть.
Поэтому я решил сделать по другому — сохранять табличную часть товаров в начале процедуры, а при завершении восстанавливать:
&НаКлиенте &Вместо("ПартнерПриИзменении") Процедура дор_ПартнерПриИзменении(Элемент) //Сохраняем табличную часть Адрес = СохранитьТЧТовары(); ПродолжитьВызов(Элемент); ВосстановитьТЧТовары(Адрес); КонецПроцедуры &НаСервере Функция СохранитьТЧТовары() ТЗ = Объект.Товары.Выгрузить(); Возврат ПоместитьВоВременноеХранилище(ТЗ, ЭтаФорма.УникальныйИдентификатор) КонецФункции &НаСервере Процедура ВосстановитьТЧТовары(Адрес) ТЗ = ПолучитьИзВременногоХранилища(Адрес); Объект.Товары.Загрузить(ТЗ); //Дальше вызовем два обработчика, чтобы корректно обновились итоги документа ОчищатьСтроки = Ложь; ОтвязатьВсеСтрокиОтЗаказа = Ложь; СкладПриИзмененииСервер(ОчищатьСтроки, ОтвязатьВсеСтрокиОтЗаказа); ЗаполнитьСлужебныеРеквизитыПоНоменклатуре(); КонецПроцедуры
Изменить контрагента в заказе не так-то просто, потому что нужно отменять проведение всех связанных реализаций, иначе 1С будет ругаться, что списано количества больше, чем заказано. Вот пример, где реализаций три:
Поэтому отделаться «малой кровью не получится», придется писать полноценную отмену проведения цепочки и заново ее проводить. Текущая реализация обрабатывается особым образом, т.к. она в текущий момент проводится:
&НаСервере Процедура ИзменитьКонтрагентаЗаказа(ТекущийОбъект) Экспорт ТекЗаказ = ТекущийОбъект.ЗаказКлиента; Если Не ЗначениеЗаполнено(ТекЗаказ) Тогда Возврат; КонецЕсли; Если ТекЗаказ.Контрагент = ТекущийОбъект.Контрагент Тогда //Сравниваем только контрагента, партнеры у контрагентов одинаковые //Партнер более широкая сущность, чем контрагенты Возврат; КонецЕсли; НачальноПроведен = ТекущийОбъект.Проведен; МассивКПроведению = Новый Массив(); З = Новый Запрос( "ВЫБРАТЬ | РеализацияТоваровУслуг.Ссылка КАК Ссылка |ИЗ | Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг |ГДЕ | РеализацияТоваровУслуг.Проведен И РеализацияТоваровУслуг.ЗаказКлиента = &Заказ"); З.УстановитьПараметр("Заказ", ТекЗаказ); Выборка = З.Выполнить().Выбрать(); Пока Выборка.Следующий() Цикл Если Выборка.Ссылка = ТекущийОбъект.Ссылка Тогда РабочийОбъект = ТекущийОбъект; Иначе //У остальных реализаций тоже меняем контрагента РабочийОбъект = Выборка.Ссылка.ПолучитьОбъект(); РабочийОбъект.Контрагент = ТекущийОбъект.Контрагент; РабочийОбъект.Партнер = ТекущийОбъект.Партнер; РабочийОбъект.Соглашение = ТекущийОбъект.Соглашение; РабочийОбъект.Договор = ТекущийОбъект.Договор; МассивКПроведению.Добавить(Выборка.Ссылка); КонецЕсли; Если НЕ ЗначениеЗаполнено(РабочийОбъект.Ссылка) Тогда Продолжить; КонецЕсли; Если РабочийОбъект.Проведен Тогда РабочийОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения); КонецЕсли; Сообщить("Распроведена реализация: " + РабочийОбъект); КонецЦикла; О = ТекЗаказ.ПолучитьОбъект(); О.Контрагент = ТекущийОбъект.Контрагент; О.Партнер = ТекущийОбъект.Партнер; О.Соглашение = ТекущийОбъект.Соглашение; О.Договор = ТекущийОбъект.Договор; О.Склад = ТекущийОбъект.Склад; Если О.Проведен Тогда О.Записать(РежимЗаписиДокумента.Проведение); Иначе О.Записать(РежимЗаписиДокумента.Запись); КонецЕсли; Сообщить("Изменен контрагент в заказе: " + О); Для Каждого СсылкаНаРеализацию ИЗ МассивКПроведению Цикл РабочийОбъект = СсылкаНаРеализацию.ПолучитьОбъект(); Попытка РабочийОбъект.Записать(РежимЗаписиДокумента.Проведение); Сообщить("Проведена реализация: " + РабочийОбъект); Исключение Сообщить("Не удалось провести реализацию: " + РабочийОбъект + ", проведите ее вручную!", СтатусСообщения.Важное); КонецПопытки; КонецЦикла; //Восстанавлием проведение текущего объекта ТекущийОбъект.Проведен = НачальноПроведен; КонецПроцедуры &НаСервере Процедура дор_ПередЗаписьюНаСервереПеред(Отказ, ТекущийОбъект, ПараметрыЗаписи) Если Отказ Тогда Возврат; КонецЕсли; ИзменитьКонтрагентаЗаказа(ТекущийОбъект); КонецПроцедуры
Попробуем распровести реализацию 149 в этой цепочке:
При этом будут выданы сообщения о распроведении и проведении других документов:
Операции производятся не в транзакции, поэтому можно допровести документы реализации вручную, если они не смогли провестись после распроведения.
По работе с этой задачей хочу заметить, что не сразу вышел на верный путь. Начал с распроведения текущей накладной. Но мне попалась такая реализация, которая была в цепочке с другими. Пришлось писать код для общего случая, когда есть цепочка реализаций.
Потом я забыл, что в других реализациях нужно менять контрагента и обработка на них спотыкалась, т.к. контрагент в заказах был уже поправлен, а в реализациях еще нет.
И наконец, для меня стало приятным сюрпризом, что при вызове из формы событие «Перед записью на сервере» не вызывается в транзакции, т.е. в случае ошибки проведения/распроведения ситуация так и фиксируется, что в принципе, удобнее пользователю.
Среда: УТ 11.4.13.46 Объем: 1.5 час.
Свежие комментарии