Правило выбора методики контроля остатков:
- новая - если для заполнения набора записей данные регистра не нужны (все данные берутся из проводимого документа);
- старая - если для заполнения набора записей нужны данные не только проводимого документа, но и регистра (выполняется сначала чтение из регистра, а потом запись в этот же регистр).
Если новая методика и приходная операция – то контроль не нужен.
Устранение дублей при проведении
В процедуре обработки проведения обработать возможные дубли номенклатуры в табличной части можно, например, сформировав простейший запрос с группировкой по Номенклатуре (синтаксические конструкции не убирал специально, для понимания использованных механизмов):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
Процедура ОбработкаПроведения(Отказ, Режим) Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | ПриходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура, | СУММА(ПриходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество |ИЗ | Документ.ПриходнаяНакладная.СписокНоменклатуры КАК ПриходнаяНакладнаяСписокНоменклатуры |ГДЕ | ПриходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка | |СГРУППИРОВАТЬ ПО | ПриходнаяНакладнаяСписокНоменклатуры.Номенклатура"; Запрос.УстановитьПараметр("Ссылка", Ссылка); РезультатЗапроса = Запрос.Выполнить(); ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать(); Пока ВыборкаДетальныеЗаписи.Следующий() Цикл Движение = Движения.ОстаткиНоменклатуры.Добавить(); Движение.ВидДвижения = ВидДвиженияНакопления.Приход; Движение.Период = Дата; Движение.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура; Движение.Количество = ВыборкаДетальныеЗаписи.Количество; КонецЦикла; // регистр ОстаткиНоменклатуры Приход Движения.ОстаткиНоменклатуры.Записывать = Истина; //{{КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА // Данный фрагмент построен конструктором. // При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!! //}}КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА //{{__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ // Данный фрагмент построен конструктором. // При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!! //}}__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ КонецПроцедуры |
[свернуть]
Старая методика контроля остатков
Итоговый код процедуры ОбработкаПроведения
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
Процедура ОбработкаПроведения(Отказ, Режим) // регистр ОстаткиНоменклатуры Расход // 1. Очистка движений документа путем записи пустого набора Движения.ОстаткиНоменклатуры.Записать(); // 2. Установка управляемых блокировок на записи тех таблиц информационной базы, // к данным которых внутри транзакции будут применены операции и чтения, и записи. Блокировка = Новый БлокировкаДанных; // указываем регистр ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиНоменклатуры"); // указываем элемент отбора виртуальной таблицы ЭлементБлокировки.УстановитьЗначение("Склад", Склад); ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный; // указываем источник данных (табличная часть в примере) ЭлементБлокировки.ИсточникДанных = СписокНоменклатуры; ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура"); Блокировка.Заблокировать(); //{{КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА // Данный фрагмент построен конструктором. // При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!! Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура, | СУММА(РасходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество |ПОМЕСТИТЬ ДанныеТЧ |ИЗ | Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры |ГДЕ | РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка | И РасходнаяНакладнаяСписокНоменклатуры.Номенклатура.ВидНоменклатуры = &ВидНоменклатуры | |СГРУППИРОВАТЬ ПО | РасходнаяНакладнаяСписокНоменклатуры.Номенклатура | |ИНДЕКСИРОВАТЬ ПО | Номенклатура |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | ДанныеТЧ.Номенклатура КАК Номенклатура, | ДанныеТЧ.Количество КАК Количество, | ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) КАК КоличествоОстаток, | ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) КАК СуммаОстаток, | ДанныеТЧ.Номенклатура.Представление КАК НоменклатураПредставление |ИЗ | ДанныеТЧ КАК ДанныеТЧ | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки( | &МоментВремени, | Номенклатура В | (ВЫБРАТЬ | ДанныеТЧ.Номенклатура КАК Номенклатура | ИЗ | ДанныеТЧ КАК ДанныеТЧ) | И Склад = &Склад) КАК ОстаткиНоменклатурыОстатки | ПО ДанныеТЧ.Номенклатура.Ссылка = ОстаткиНоменклатурыОстатки.Номенклатура.Ссылка"; Запрос.УстановитьПараметр("ВидНоменклатуры", Перечисления.ВидыНоменклатуры.Товар); Запрос.УстановитьПараметр("МоментВремени", МоментВремени()); Запрос.УстановитьПараметр("Склад", Склад); Запрос.УстановитьПараметр("Ссылка", Ссылка); РезультатЗапроса = Запрос.Выполнить(); ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать(); Пока ВыборкаДетальныеЗаписи.Следующий() Цикл // если товаров не хватает Если ВыборкаДетальныеЗаписи.Количество > ВыборкаДетальныеЗаписи.КоличествоОстаток Тогда НехваткаКоличество = ВыборкаДетальныеЗаписи.Количество - ВыборкаДетальныеЗаписи.КоличествоОстаток; Сообщение = Новый СообщениеПользователю; Сообщение.Текст = "Количество товаров номенклатуры "+ ВыборкаДетальныеЗаписи.НоменклатураПредставление + " недостаточно для проведения документа (не хватает " + НехваткаКоличество + " единиц)."; Сообщение.Сообщить(); //отмена проведения Отказ = Истина; // продолжаем обход записей выборки Продолжить; КонецЕсли; // если контроль пройден (проведение не отменено), то формируем движения Если НЕ Отказ Тогда Движение = Движения.ОстаткиНоменклатуры.Добавить(); Движение.ВидДвижения = ВидДвиженияНакопления.Расход; Движение.Период = Дата; Движение.Склад = Склад; Движение.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура; Движение.Количество = ВыборкаДетальныеЗаписи.Количество; // решим "проблему копеек" Если ВыборкаДетальныеЗаписи.Количество = ВыборкаДетальныеЗаписи.КоличествоОстаток Тогда Движение.Сумма = ВыборкаДетальныеЗаписи.СуммаОстаток Иначе Движение.Сумма = ВыборкаДетальныеЗаписи.Количество/ВыборкаДетальныеЗаписи.КоличествоОстаток * ВыборкаДетальныеЗаписи.СуммаОстаток; КонецЕсли; КонецЕсли; КонецЦикла; //}}КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА Движения.ОстаткиНоменклатуры.Записывать = Истина; //{{__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ // Данный фрагмент построен конструктором. // При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!! //}}__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ КонецПроцедуры |
[свернуть]
Алгоритм "старой" методики контроля остатков 1С:
- Программное удаление существующих движений документа путем записи «пустого набора»
Код12// 1. Очистка движений документа путем записи пустог8о набораДвижения.ОстаткиНоменклатуры.Записать();[свернуть]
- Установка управляемых блокировок на записи тех таблиц информационной базы, к данным которых внутри транзакции будут применены операции и чтения, и записи (найти в Синтакс-помощнике "Блокировка данных", скопировать пример, вставить в процедуру "Обработка проведения" и временно закомментировать).
Код12345678910111213141516// регистр ОстаткиНоменклатуры Расход// 1. Очистка движений документа путем записи пустого набораДвижения.ОстаткиНоменклатуры.Записать();// 2. Установка управляемых блокировок на записи тех таблиц информационной базы,// к данным которых внутри транзакции будут применены операции и чтения, и записи.//Блокировка = Новый БлокировкаДанных;//ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ТоварыНаСкладах");//ЭлементБлокировки.УстановитьЗначение("Качество", Справочники.Качество.НайтиПоКоду("1"));//ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;//ЭлементБлокировки.ИсточникДанных = ДокументОбъект.ВозвратнаяТара;//ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");//ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Склад", "Склад");//Блокировка.Заблокировать();[свернуть]
- Получение необходимых данных для формирования набора записей в регистр:
- на основании данных проводимого документа:
- при использовании табличной части документа - ставим условие по ссылке (вкладка "Условия");
- ставим дополнительные условия (по задаче, например, по виду номенклатуры) (вкладка "Условия");
- ставим группировки (например, если табличная часть может содержать несколько строк с одинаковой номенклатурой - их надо свернуть: поле группировки - номенклатура, суммируемое поле - количество) (вкладка "Группировка");
- если данные из документа далее используются в нескольких местах (например, при соединении таблиц и получении остатков), то их необходимо поместить во временную таблицу (вкладка "Дополнительно");
- на основании данных других объектов конфигурации (за исключением данных записываемого регистра);
- на основании данных записываемого регистра:
- если данные регистра числовые - обязательно использовать функцию ЕСТЬNULL(<регистр.данные>, 0).
- на основании данных проводимого документа:
- Контроль полученных данных (в первую очередь – остатков по регистру):
- выбор регистра, из которого получаем информацию (при этом, например, если нужны только остатки, то выбор регистра
ОстаткиИОбороты
вместоОстатки
будет ошибкой):- если данные регистра числовые - обязательно использовать функцию ЕСТЬNULL(<регистр.данные>, 0).
- установка параметров виртуальной таблицы (Период, Условие - если значение выбора из регистра ограничено, например, табличной частью документа)
Пример условия1234567Номенклатура В (ВЫБРАТЬДанныеТЧ.Номенклатура КАК НоменклатураИЗДанныеТЧ КАК ДанныеТЧ) И Склад = &Склад// Номенклатура выбирается из списка табличной части документа// Склад имеет конкретное значение, которое передается в параметр[свернуть]
- задать условия связи;
- если необходимо выдать пользователю сообщение, то в сообщение передавать не ссылку на объект, а представление.
Пример запроса1234567891011121314151617181920212223242526272829303132333435"ВЫБРАТЬ| РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура,| СУММА(РасходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество|ПОМЕСТИТЬ ДанныеТЧ|ИЗ| Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры|ГДЕ| РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка| И РасходнаяНакладнаяСписокНоменклатуры.Номенклатура.ВидНоменклатуры = &ВидНоменклатуры||СГРУППИРОВАТЬ ПО| РасходнаяНакладнаяСписокНоменклатуры.Номенклатура||ИНДЕКСИРОВАТЬ ПО| Номенклатура|;||////////////////////////////////////////////////////////////////////////////////|ВЫБРАТЬ| ДанныеТЧ.Номенклатура КАК Номенклатура,| ДанныеТЧ.Количество КАК Количество,| ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) КАК КоличествоОстаток,| ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) КАК СуммаОстаток,| ДанныеТЧ.Номенклатура.Представление КАК НоменклатураПредставление|ИЗ| ДанныеТЧ КАК ДанныеТЧ| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(| &МоментВремени,| Номенклатура В| (ВЫБРАТЬ| ДанныеТЧ.Номенклатура КАК Номенклатура| ИЗ| ДанныеТЧ КАК ДанныеТЧ)| И Склад = &Склад) КАК ОстаткиНоменклатурыОстатки| ПО ДанныеТЧ.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура";[свернуть]
- установить параметры, использованные в запросе;
Код, сформированный кoнструктором запроса с oбработкой результата12345678910111213141516171819202122232425262728293031323334353637383940414243444546Запрос = Новый Запрос;Запрос.Текст ="ВЫБРАТЬ| РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура,| СУММА(РасходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество|ПОМЕСТИТЬ ДанныеТЧ|ИЗ| Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры|ГДЕ| РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка| И РасходнаяНакладнаяСписокНоменклатуры.Номенклатура.ВидНоменклатуры = &ВидНоменклатуры||СГРУППИРОВАТЬ ПО| РасходнаяНакладнаяСписокНоменклатуры.Номенклатура||ИНДЕКСИРОВАТЬ ПО| Номенклатура|;||////////////////////////////////////////////////////////////////////////////////|ВЫБРАТЬ| ДанныеТЧ.Номенклатура КАК Номенклатура,| ДанныеТЧ.Количество КАК Количество,| ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) КАК КоличествоОстаток,| ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) КАК СуммаОстаток,| ДанныеТЧ.Номенклатура.Представление КАК НоменклатураПредставление|ИЗ| ДанныеТЧ КАК ДанныеТЧ| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(| &МоментВремени,| Номенклатура В| (ВЫБРАТЬ| ДанныеТЧ.Номенклатура КАК Номенклатура| ИЗ| ДанныеТЧ КАК ДанныеТЧ)| И Склад = &Склад) КАК ОстаткиНоменклатурыОстатки| ПО ДанныеТЧ.Номенклатура.Ссылка = ОстаткиНоменклатурыОстатки.Номенклатура.Ссылка";Запрос.УстановитьПараметр("ВидНоменклатуры", Перечисления.ВидыНоменклатуры.Товар);Запрос.УстановитьПараметр("МоментВремени", МоментВремени());Запрос.УстановитьПараметр("Склад", Склад);Запрос.УстановитьПараметр("Ссылка", Ссылка);РезультатЗапроса = Запрос.Выполнить();ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();[свернуть]
- выполнить контроль остатков внутри выборки, сформировать сообщение пользователю (например, в случае нехватки номенклатуры) и разрешить/запретить проведение документа;
Код1234567891011121314151617Пока ВыборкаДетальныеЗаписи.Следующий() Цикл// если товаров не хватаетЕсли ВыборкаДетальныеЗаписи.Количество > ВыборкаДетальныеЗаписи.КоличествоОстаток ТогдаСообщение = Новый СообщениеПользователю;Сообщение.Текст = "Количество товаров номенклатуры "+ВыборкаДетальныеЗаписи.НоменклатураПредставление+" недостаточно для проведения документа (не хватает "+ВыборкаДетальныеЗаписи.Количество - ВыборкаДетальныеЗаписи.КоличествоОстаток+ "единиц).";Сообщение.Сообщить();//отмена проведенияОтказ = Истина;// продолжаем обход записей выборкиПродолжить;КонецЕсли;КонецЦикла;[свернуть]
- если контроль пройден успешно, то сформировать набор записей регистров (при этом предусмотреть проверку деления на "0" в коде или через проверку заполнения поля);
Код1234567891011121314151617181920// если контроль пройден (проведение не отменено), то формируем движенияЕсли НЕ Отказ ТогдаДвижение = Движения.ОстаткиНоменклатуры.Добавить();Движение.ВидДвижения = ВидДвиженияНакопления.Расход;Движение.Период = Дата;Движение.Склад = Склад;Движение.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура;Движение.Количество = ВыборкаДетальныеЗаписи.Количество;// решим "проблему копеек"Если ВыборкаДетальныеЗаписи.Количество = ВыборкаДетальныеЗаписи.КоличествоОстатокТогдаДвижение.Сумма = ВыборкаДетальныеЗаписи.СуммаОстатокИначеДвижение.Сумма = ВыборкаДетальныеЗаписи.Количество/ВыборкаДетальныеЗаписи.КоличествоОстаток* ВыборкаДетальныеЗаписи.СуммаОстаток;КонецЕсли;КонецЕсли;[свернуть]
- записать движения;
Код1Движения.ОстаткиНоменклатуры.Записывать = Истина;[свернуть]
- выбор регистра, из которого получаем информацию (при этом, например, если нужны только остатки, то выбор регистра
- Перейти в пользовательский режим 1С, ввести нужную информацию (номенклатуру, виды номенклатуры, приход и расход, и т.д.) и проверить правильность контроля остатков и проведения документа.
- Отредактировать код блокировок (см. п. 2), устанавливаемых на записи тех таблиц информационной базы, к данным которых внутри транзакции будут применены операции и чтения, и записи (в соответствии с решаемой задачей).
Код123456789101112131415161718// 2. Установка управляемых блокировок на записи тех таблиц информационной базы,// к данным которых внутри транзакции будут применены операции и чтения, и записи.Блокировка = Новый БлокировкаДанных;// указываем регистрЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиНоменклатуры");// указываем элемент отбора виртуальной таблицыЭлементБлокировки.УстановитьЗначение("Склад", Склад);ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;// указываем источник данных (табличная часть в примере)ЭлементБлокировки.ИсточникДанных = СписокНоменклатуры;ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");Блокировка.Заблокировать();[свернуть]
Новая методика контроля остатков
Новая методика контроля остатков используется, если для заполнения набора записей данные регистра не нужны (операция чтения из регистра не выполняется, все данные берутся из проводимого документа).
Итоговый код процедуры ОбработкаПроведения
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
Процедура ОбработкаПроведения(Отказ, РежимПроведения) Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура, | СУММА(РасходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество |ИЗ | Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры |ГДЕ | РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка | И РасходнаяНакладнаяСписокНоменклатуры.Номенклатура.ВидНоменклатуры = &ВидНоменклатуры | |СГРУППИРОВАТЬ ПО | РасходнаяНакладнаяСписокНоменклатуры.Номенклатура"; Запрос.УстановитьПараметр("ВидНоменклатуры", Перечисления.ВидыНоменклатуры.Товар); Запрос.УстановитьПараметр("Ссылка", Ссылка); РезультатЗапроса = Запрос.Выполнить(); ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать(); Пока ВыборкаДетальныеЗаписи.Следующий() Цикл // регистр ОстаткиНоменклатуры Расход Движение = Движения.ОстаткиНоменклатуры.Добавить(); Движение.ВидДвижения = ВидДвиженияНакопления.Расход; Движение.Период = Дата; Движение.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура; Движение.Склад = Склад; Движение.Количество = ВыборкаДетальныеЗаписи.Количество; КонецЦикла; Движения.ОстаткиНоменклатуры.БлокироватьДляИзменения = Истина; Движения.ОстаткиНоменклатуры.Записывать = Истина; Движения.Записать(); Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | ОстаткиНоменклатурыОстатки.Номенклатура КАК Номенклатура, | ОстаткиНоменклатурыОстатки.КоличествоОстаток КАК КоличествоОстаток, | ОстаткиНоменклатурыОстатки.Номенклатура.Представление КАК НоменклатураПредставление |ИЗ | РегистрНакопления.ОстаткиНоменклатуры.Остатки( | &Граница, | Номенклатура В (&СписокТоваров) | И Склад = &Склад) КАК ОстаткиНоменклатурыОстатки |ГДЕ | ОстаткиНоменклатурыОстатки.КоличествоОстаток < 0"; Запрос.УстановитьПараметр("Граница", Новый Граница(МоментВремени())); Запрос.УстановитьПараметр("Склад", Склад); Запрос.УстановитьПараметр("СписокТоваров", СписокНоменклатуры.ВыгрузитьКолонку("Номенклатура")); РезультатЗапроса = Запрос.Выполнить(); ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать(); Пока ВыборкаДетальныеЗаписи.Следующий() Цикл Сообщение = Новый СообщениеПользователю; Сообщение.Текст = "По номенклатуре "+ВыборкаДетальныеЗаписи.НоменклатураПредставление + " не хватает товара. Перерасход: " +ВыборкаДетальныеЗаписи.КоличествоОстаток ; Сообщение.Сообщить(); Отказ = Истина; КонецЦикла; КонецПроцедуры |
[свернуть]
Алгоритм "новой" методики контроля остатков 1С:
- Получение необходимых данных для формирования набора записей в регистр:
- на основании данных проводимого документа:
- при использовании табличной части документа - ставим условие по ссылке (вкладка "Условия");
- ставим дополнительные условия (по задаче, например, по виду номенклатуры) (вкладка "Условия");
- ставим группировки (например, если табличная часть может содержать несколько строк с одинаковой номенклатурой - их надо свернуть: поле группировки - номенклатура, суммируемое поле - количество) (вкладка "Группировка");
- на основании данных других объектов конфигурации (за исключением данных записываемого регистра).
Код в процедуре "Обработка проведения"123456789101112131415161718192021222324Запрос = Новый Запрос;Запрос.Текст ="ВЫБРАТЬ| РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура,| СУММА(РасходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество|ИЗ| Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры|ГДЕ| РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка| И РасходнаяНакладнаяСписокНоменклатуры.Номенклатура.ВидНоменклатуры = &ВидНоменклатуры||СГРУППИРОВАТЬ ПО| РасходнаяНакладнаяСписокНоменклатуры.Номенклатура";Запрос.УстановитьПараметр("ВидНоменклатуры", Перечисления.ВидыНоменклатуры.Товар);Запрос.УстановитьПараметр("Ссылка", Ссылка);РезультатЗапроса = Запрос.Выполнить();ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();Пока ВыборкаДетальныеЗаписи.Следующий() Цикл// Вставить обработку выборки ВыборкаДетальныеЗаписиКонецЦикла;[свернуть]
- на основании данных проводимого документа:
- Формирование набора записей регистра.
Код123456789Пока ВыборкаДетальныеЗаписи.Следующий() Цикл// регистр ОстаткиНоменклатуры РасходДвижение = Движения.ОстаткиНоменклатуры.Добавить();Движение.ВидДвижения = ВидДвиженияНакопления.Расход;Движение.Период = Дата;Движение.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура;Движение.Склад = Склад;Движение.Количество = ВыборкаДетальныеЗаписи.Количество;КонецЦикла;[свернуть]
- Запись всех модифицированных наборов.
Код123456// блокирует для исключения одновременной записи другим регистратором,// игнорируя значение разделителя итогов регистраДвижения.ОстаткиНоменклатуры.БлокироватьДляИзменения = Истина;Движения.ОстаткиНоменклатуры.Записывать = Истина;Движения.Записать();[свернуть]
- Контроль данных, используемых при заполнении набора записей (в первую очередь – остатков по регистру):
- формирование запроса к регистру, в который были записаны движения, для получения остатков, при этом:
- в тексте запроса определить параметры виртуальной таблицы остатков и условие: остатки меньше 0;
- в коде установить границу момента времени, на которую получаем остатки и список товаров, подлежащих контролю (выбираются из табличной части либо по объектной модели - как в коде ниже, либо с использованием временной таблицы - как в примере по "старой" методике);
Код1234567891011121314151617Запрос = Новый Запрос;Запрос.Текст ="ВЫБРАТЬ| ОстаткиНоменклатурыОстатки.Номенклатура КАК Номенклатура,| ОстаткиНоменклатурыОстатки.КоличествоОстаток КАК КоличествоОстаток,| ОстаткиНоменклатурыОстатки.Номенклатура.Представление КАК НоменклатураПредставление|ИЗ| РегистрНакопления.ОстаткиНоменклатуры.Остатки(| &Граница,| Номенклатура В (&СписокТоваров)| И Склад = &Склад) КАК ОстаткиНоменклатурыОстатки|ГДЕ| ОстаткиНоменклатурыОстатки.КоличествоОстаток < 0";Запрос.УстановитьПараметр("Граница", Новый Граница(МоментВремени()));Запрос.УстановитьПараметр("Склад", Склад);Запрос.УстановитьПараметр("СписокТоваров", СписокНоменклатуры.ВыгрузитьКолонку("Номенклатура"));[свернуть]
- если контроль не пройден (остатки меньше 0), то отменяем проведение.
- формирование запроса к регистру, в который были записаны движения, для получения остатков, при этом: