|
Проведение документа, запись в регистр, вынести в общий модуль. | ☑ | ||
---|---|---|---|---|
0
ermola
12.07.17
✎
14:50
|
Доброго.
Посоветуйте как из процедуры Проведение документа, запись в регистр, вынести в общий модуль. Оптимальный вариант. А то в цикле запихать в структуру а в общем модуме в цикле разбирать как-то не то. Мне кажется Вот для примера простое, сделано кострутором по быстрому. Процедура ОбработкаПроведения(Отказ, Режим) //{{__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ // Данный фрагмент построен конструктором. // При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!! // регистр ОстаткиНаСкладах Приход Движения.ОстаткиНаСкладах.Записывать = Истина; Для Каждого ТекСтрокаТовары Из Товары Цикл Движение = Движения.ОстаткиНаСкладах.Добавить(); Движение.ВидДвижения = ВидДвиженияНакопления.Приход; Движение.Период = Дата; Движение.Номенклатура = ТекСтрокаТовары.Номенклатура; Движение.Серия = ТекСтрокаТовары.Серия; Движение.Склад = Склад; Движение.Цистерна = Цистерна; Движение.Количество = ТекСтрокаТовары.Количество; КонецЦикла; //}}__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ КонецПроцедуры |
|||
1
Spieluhr
12.07.17
✎
14:51
|
см в типовых
|
|||
2
ermola
12.07.17
✎
14:53
|
(1) В типовой УПП такого комбайна сделали.
|
|||
3
Лефмихалыч
12.07.17
✎
15:01
|
1. берешь модуль ПроведениеСервер из любой типовой. Целиком. Просто - копе...пасте
2. в модуле документа: Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения) Если ОбменДанными.Загрузка Тогда Возврат; КонецЕсли; ДополнительныеСвойства.Вставить("ЭтоНовый", ЭтоНовый()); ДополнительныеСвойства.Вставить("РежимЗаписи", РежимЗаписи); КонецПроцедуры Процедура ОбработкаПроведения(Отказ, РежимПроведения) // Инициализация дополнительных свойств для проведения документа ПроведениеСервер.ИнициализироватьДополнительныеСвойстваДляПроведения(Ссылка, ДополнительныеСвойства, РежимПроведения); ДополнительныеСвойства.Вставить("МоментВремени", МоментВремени()); // Инициализация данных документа Документы.ИмяТвоегоДокумента.ИнициализироватьДанныеДокумента(Ссылка, ДополнительныеСвойства); // Подготовка наборов записей ПроведениеСервер.ПодготовитьНаборыЗаписейКРегистрацииДвижений(ЭтотОбъект); // Отражение в разделах учета ПроведениеСервер.СформироватьДвиженияДокумента(ДополнительныеСвойства, Движения); КонецПроцедуры 3. В модуле менеджера документа пишешь: Процедура ИнициализироватьДанныеДокумента(ДокументСсылка, ДополнительныеСвойства, Регистры = Неопределено) Экспорт Запрос = Новый Запрос; Запрос.МенеджерВременныхТаблиц = ДополнительныеСвойства.ДляПроведения.СтруктураВременныеТаблицы.МенеджерВременныхТаблиц; ЗаполнитьПараметрыИнициализации(Запрос, ДокументСсылка); Для каждого КлючЗначение Из Новый Структура("МоментВремени,ЭтоНовый,РежимЗаписи,РежимПроведения") Цикл // сюда можно добавить все, что присунули в обработке проведения Значение = Неопределено; Если ДополнительныеСвойства.Свойство(КлючЗначение.Ключ, Значение) Тогда Запрос.Параметры.Вставить(КлючЗначение.Ключ, Значение); КонецЕсли; КонецЦикла; //////////////////////////////////////////////////////////////////////////// // Сформируем текст запроса ТекстыЗапроса = Новый СписокЗначений; ТекстЗапросаТаблицаИмяРегистраНакопления(Запрос, ТекстыЗапроса, Регистры); ПроведениеСервер.ИницализироватьТаблицыДляДвижений(Запрос, ТекстыЗапроса, ДополнительныеСвойства.ТаблицыДляДвижений, Истина); КонецПроцедуры // заполняет структу параметров запроса значениями, получаемыми из шапки документа и прочих констант // замес процедуры в том, что она это все одним запросом получает по ссылке. Ну, - должна, во всяком случае Процедура ЗаполнитьПараметрыИнициализации(Запрос, ДокументСсылка) Запрос.УстановитьПараметр("Ссылка", ДокументСсылка); Запрос.Текст = // здесь перечисли поля документа, которые нужны, как параметры в запросах формирования таблиц движений "ВЫБРАТЬ | Документ1.Номер, | Документ1.Дата, | Документ1.Реквизит1, | Документ1.Реквизит2 |ИЗ | Документ.Документ1 КАК Документ1 |ГДЕ | Документ1.Ссылка = &Ссылка"; Результат = Запрос.Выполнить(); Реквизиты = Результат.Выбрать(); Реквизиты.Следующий(); Для каждого Колонка Из Результат.Колонки Цикл Запрос.УстановитьПараметр(Колонка.Имя, Реквизиты[Колонка.Имя]); КонецЦикла; Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДата()); КонецПроцедуры Функция ТекстЗапросаТаблицаИмяРегистраНакопления(Запрос, ТекстыЗапроса, Регистры) ИмяРегистра = "ИмяРегистраНакопления"; Если НЕ ПроведениеСервер.ТребуетсяТаблицаДляДвижений(ИмяРегистра, Регистры) Тогда Возврат ""; КонецЕсли; // это запрос, который должен вернуть таблицу, которую потом ПроведениеСервер сможет Загрузить() в набор движений регистра ТекстЗапроса = "ВЫБРАТЬ | &Дата КАК Период, | &Реквизит1 как Измерение1, | ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход) КАК ВидДвижения, | &Реквизит2 как Измерение2, | Документ1ТабличнаяЧасть1.Реквизит1 КАК Измерение3, | Документ1ТабличнаяЧасть1.Число1 КАК Ресурс1, | Документ1ТабличнаяЧасть1.Число2 КАК Ресурс2, | Документ1ТабличнаяЧасть1.Число3 КАК Ресурс3 |ИЗ | Документ.Документ1.ТабличнаяЧасть1 КАК Документ1ТабличнаяЧасть1 |ГДЕ | Документ1ТабличнаяЧасть1.Ссылка = &Ссылка"; ТекстыЗапроса.Добавить(ТекстЗапроса, ИмяРегистра); Возврат ТекстЗапроса; КонецФункции |
|||
4
Лефмихалыч
12.07.17
✎
15:03
|
+(3) Нюанс про вспомогательные временные таблицы.
Для вспомогательных нельзя указывать имя регистра, то есть их надо добавлять в список текстов без второного параметра: ТекстыЗапроса.Добавить(ТекстЗапросаВспомогательнойТаблицы); ПроведениеСервер считает, что, если представление задано, то в представлении имя регистра указано и надо Движения[Представление].Загрузить(Выгрузить()) |
|||
5
Лефмихалыч
12.07.17
✎
15:08
|
По началу это выглядит, конечно, как инопланетянство, но после некоторого периода привыкания ты оцениваешь всю офигенность модуля ПроведениеСервер.
Некоторые говорят про сложность отладки. Да, она не тривиальная получается, ибо отлаживать надо не код, а запросы. НО! Если у вас документ двигает 100500 регистров, то отладка становится ни фига не простой даже и при традиционном дедовском подходе. А тут, в отличие от дедовского способа, все данные для проведения в одном запросе получаюся |
|||
6
Лефмихалыч
12.07.17
✎
15:24
|
Даже вот так:
Пример использования ПроведениеСервер.dt Шаблоны кода, которые всё упрощают Проведение сервер.st |
|||
7
ermola
12.07.17
✎
16:08
|
О чем я и говорил. Вот я до пункта три все понял.
А на нем завис. Конкретно так завис. |
|||
8
Лефмихалыч
12.07.17
✎
19:27
|
(7) задавай вопросы. Что не понятно?
Обработка проведения дергает ИнициализироватьДанныеДокумента() из модуля менеджера. А ИнициализироватьДанныеДокумента() выполняет последовательно все функции, формирующие таблицы движений и складывающие эти таблицы в ДопонительныеСвойства объекта документа. Потом обработка проведения дергает СформироватьДвиженияДокумента(), которая берет структуру таблиц из ДополнительныеСвойства объекта и делает из них наборы записей. |
|||
9
rozer76
13.07.17
✎
09:56
|
(8) а зачем в "ПодготовитьНаборыЗаписейКРегистрацииДвижений"
Если НЕ ЭтоНовыйДокумент Тогда Для Каждого Набор Из Объект.Движения Цикл Набор.Записывать = Истина; КонецЦикла; КонецЕсли; когда в "СформироватьДвиженияДокумента" всегда НаборДвижений.Записывать = Истина; смысл какой тайный ? |
|||
10
Лефмихалыч
13.07.17
✎
09:59
|
(9) не по адресу вопрос. Это модуль из ЕРП 2.1 с какими-то моими добавками несущественными. Не помню, правда, какими именно, но это - точно не мое.
|
|||
11
rozer76
13.07.17
✎
10:11
|
(10) да в курсе что в типовых новомодных такое, думал вы разобрались почему так
|
|||
12
Лефмихалыч
13.07.17
✎
10:51
|
(11) ну, вот это (9) конкретное, оно на функционал-то не влияет. И не делает вот эту парадигму плохой.
Вероятно ПодготовитьНаборыЗаписейКРегистрацииДвижений() и СформироватьДвиженияДокумента() писали в разное время разные люди, которые руководствовались одними и теми же регламентами, которые говорят |
|||
13
ermola
13.07.17
✎
13:20
|
Вот это кусок кода что делает?
Для каждого КлючЗначение Из Новый Структура("МоментВремени,ЭтоНовый,РежимЗаписи,РежимПроведения") Цикл // сюда можно добавить все, что присунули в обработке проведения Значение = Неопределено; |
|||
14
1dvd
13.07.17
✎
13:23
|
(13) когда за буквы платят, и не такого понапишешь...
|
|||
15
Лефмихалыч
13.07.17
✎
13:33
|
(13) устанавливает в запрос параметры МоментВремени,ЭтоНовый,РежимЗаписи и РежимПроведения, если такие элементы есть в структуре ДополнительныеПараметры
без цикла по структуре там было бы дохера ЕслиКогдаТогда. А так - 6 строк и при добавлении таких параметров строк не добавится |
|||
16
1dvd
13.07.17
✎
13:35
|
(15) чего? Запрос? Где?
|
|||
17
Лефмихалыч
13.07.17
✎
13:35
|
(16) глаза открой уже. В (3)
|
|||
18
ermola
13.07.17
✎
14:20
|
(15) что в структуру запихивают параметры МоментВремени,ЭтоНовый,РежимЗаписи и РежимПроведения это я догадался, зачем мне структуру формировать
Это зачем пририсовывать? // сюда можно добавить все, что присунули в обработке проведения |
|||
19
Лефмихалыч
13.07.17
✎
15:05
|
(18) структура там создается, чтобы обеспечить итерацию по параметрам. Если бы 1С позволяла налету объявлять и инициализировать массивы, как, например, в java, не нужна была бы структура, а было бы как-то так
Для каждого Элемент из {"МоментВремени","ЭтоНовый","РежимЗаписи","РежимПроведения"} Цикл у 1С просто другой коллекции, которую можно инициализировать в момент объявления и которая бы поддерживала итерацию, нет |
|||
20
Лефмихалыч
13.07.17
✎
15:07
|
(18) а! я кажется понял, что вызывает ступор.
Этот цикл нужен, чтобы в параметры запроса воткнуть вот эти параметры https://i.imgur.com/Cg3VTNt.png да, это слегка хтонично, согласен, но я немножечко торопился, когда это делал. На самом деле это не так удобно, как хотелось бы, но просто это первое, что пришло в голову. |
|||
21
ermola
13.07.17
✎
15:17
|
Нет с этим то как все ясно это параметры загоняем.
Вот этот комментарий к чему? // сюда можно добавить все, что присунули в обработке проведения Что присовывать? И зачем? По идее там нужен некий код. |
|||
22
Лефмихалыч
13.07.17
✎
15:21
|
(21) ну, это как раз неудобно. В модуле документа у тебя могут появиться какие-то значения, которые ты бы хотел использовать в запросах, генерирующих наборы записей. Такие значения ты в модуле документа добавляешь в ДополнительныеСвойства, а потом в модуле менеджера добавляешь имя элемента структуры ДополнительныеСвойства в объявление это структуры. Можно, конечно, было ограничиться добавлением только в модуле объекта, но мне это понравилось ни чуть не больше, чем то, что в итоге ты видишь.
|
|||
23
Лефмихалыч
13.07.17
✎
15:24
|
мда, красноречие мне сегодня явно отказывает. Короче, эта структура и цикл по ней вот для этого
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения) Если ОбменДанными.Загрузка Тогда Возврат; КонецЕсли; ДополнительныеСвойства.Вставить("ЭтоНовый", ЭтоНовый()); ДополнительныеСвойства.Вставить("РежимЗаписи", РежимЗаписи); ДополнительныеСвойства.Вставить("КакоеНибудьХитроеЗначение", ХитроеЗначение); // вот тут оно появилось КонецПроцедуры //.... Процедура ИнициализироватьДанныеДокумента(ДокументСсылка, ДополнительныеСвойства, Регистры = Неопределено) Экспорт //... Для каждого КлючЗначение Из Новый Структура("МоментВремени,ЭтоНовый,РежимЗаписи,РежимПроведения,КакоеНибудьХитроеЗначение") Цикл // вот тут мы обеспечиваем, чтобы оно попало в параметры запроса |
|||
24
ermola
13.07.17
✎
15:36
|
Ага, это необязательно, про запас.
|
|||
25
ermola
13.07.17
✎
15:40
|
Тогда зачем запрос последний, с предыдущий понял, это насобирать данных.
И непонятно как в этом алгоритме получить что товара на остатке не хватает? |
|||
26
Лефмихалыч
13.07.17
✎
20:04
|
(25) который из запросов ты называешь последним?
Проверка на остатки - отдельный запрос во временную таблицу, в которой будут только те строки, для которых нет остатка. Добавлять текст запроса для этой таблицы в СписокЗапросов без второго параметра. В обработке проведения можешь, используя менеджер временных таблиц из ДополнительныеСвойства выбрать из этой таблицы все Для показа пользователю. Опять каша получилась. До компа доберусь - набросаю пример |
|||
27
Лефмихалыч
13.07.17
✎
20:08
|
+(26) или еще можно после СформироватьДвиженияДокумента() обычным запросом выгрести получившиеся отрицательные остатки и, если они есть, Отказ = Истина. Так, может, даже удобнее, хотя и - отдельный запрос.
|
|||
28
Лефмихалыч
13.07.17
✎
20:15
|
Хотя проще всего отрицательные остатки отдельным запросом перед всей этой кутерьмой в обработке проведения проверить. Запрос по отрицательным остаткам либо пустой вернется и тогда не велики затраты, либо не пустой и тогда запросы для проведения выполнять смысла нет.
В последней конфе у меня так и сделано |
|||
29
Лефмихалыч
13.07.17
✎
20:39
|
(26) здесь я имел в виду следующее (основываясь на примере из (6):
// модуль менеджера Функция ТекстЗапросаТаблицаРегистрНакопления1(Запрос, ТекстыЗапроса, Регистры) ИмяРегистра = "РегистрНакопления1"; Если НЕ ПроведениеСервер.ТребуетсяТаблицаДляДвижений(ИмяРегистра, Регистры) Тогда Возврат ""; КонецЕсли; //////////////////////////////////////// //ПРОВЕРКА ОСТАТКОВ //////////////////////////////////////// ТекстЗапроса = "ВЫБРАТЬ |Номенклатура, |КоличествоОстаток, |КоличествоПоДокументу |Поместить ОтрицательныеОстатки |// тут тушка запроса, которая не интересна |"; ТекстыЗапроса.Добавить(ТекстЗапроса); // NB! Второго параметра нет! ТекстЗапроса = "ВЫБРАТЬ | &Дата КАК Период, | &Реквизит1 как Измерение1, | ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход) КАК ВидДвижения, | &Реквизит2 как Измерение2, | Документ1ТабличнаяЧасть1.Реквизит1 КАК Измерение3, | Документ1ТабличнаяЧасть1.Число1 КАК Ресурс1, | Документ1ТабличнаяЧасть1.Число2 КАК Ресурс2, | Документ1ТабличнаяЧасть1.Число3 КАК Ресурс3 |ИЗ | Документ.Документ1.ТабличнаяЧасть1 КАК Документ1ТабличнаяЧасть1 |ГДЕ | Документ1ТабличнаяЧасть1.Ссылка = &Ссылка"; ТекстыЗапроса.Добавить(ТекстЗапроса, ИмяРегистра); Возврат ТекстЗапроса; КонецФункции // модуль объекта Процедура ОбработкаПроведения(Отказ, РежимПроведения) // Инициализация дополнительных свойств для проведения документа ПроведениеСервер.ИнициализироватьДополнительныеСвойстваДляПроведения(Ссылка, ДополнительныеСвойства, РежимПроведения); ДополнительныеСвойства.Вставить("МоментВремени", МоментВремени()); // Инициализация данных документа Документы.Документ1.ИнициализироватьДанныеДокумента(Ссылка, ДополнительныеСвойства); Если ПроверкаОтрицательныхОстатков(ДополнительныеСвойства.МенеджерВременныхТаблиц) Тогда Отказ = истина; Возврат; КонецЕсли; // Подготовка наборов записей ПроведениеСервер.ПодготовитьНаборыЗаписейКРегистрацииДвижений(ЭтотОбъект); // Отражение в разделах учета ПроведениеСервер.СформироватьДвиженияДокумента(ДополнительныеСвойства, Движения); КонецПроцедуры // если истина, то все хорошо, если ложь, значит остатков не хватает Функция ПроверкаОтрицательныхОстатков(МенеджерВременныхТаблиц) Запрос = Новый Запрос; ЗАпрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц; Запрос.Текст = "ВЫБРАТЬ | ВТ.Номенклатура, | ВТ.КоличествоОтаток, | ВТ.КоличествоПоДокументу |ИЗ ОтрицательныеОстатки как ВТ"; Выборка = Запрос.Выполнить().Выбрать(); Пока Выборка.Следующий() Цикл // сообщить пользователю, что остатков нет КонецЦикла; Возврат Выборка.Количество()=0; // если пусто, то все хорошо, отрицательных остатков не будет КонецФункции запроса, конечно же, все равно два, что есть, то есть. МОжно и один запрос - добавить вспомогательную таблицу в ТекстыЗапроса с каким-то именем и потом таблицу с этим именем удалять из ДополнительныеСвойства.Таблицы, но это тоже громоздко. Или допилить что-то в ПроведениеСервер.ИницализироватьТаблицыДляДвижений(), чтобы она умела такие таблицы опознавать и складывать куда-то отдельноЮ а не просто игнорить, как сейчас. В общем, тут свобода творчества |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |