8plus.ru — это отчеты и обработки 1С только версии 8 и только для типовых конфигураций!

Партионный учет в 1с8 УТП, обработка для выравнивания в случае катастрофы
Инструкция:
Версия для печати

Недостатки системы 1с предприятия 8 типовой конфигурации Управление Торговым предприятием в разрезе ведения партионного учета состоит в следующем.

Как бы мы не настраивали систему и не заставляли ее при непосредственном списании партий контролировать остатки по регистрам остатков и по регистрам партий, без доработок и усовершенствования механизмов система этого делать не будет, она будет замечательно уведомлять вас о том что определенное количество товара не списано по партиям или остатки товаров уходят в минус, но запрещать вам делать это не будет. Хуже еще если в параметрах учета настроено не списывать партии при проведении документов, тогда при выполнении обработки проведения по партиям (если она конечно вообще выполняется) партии товаров будут уходить в минус, чего быть не должно. Поэтому в критической ситуации поэтапно нужно сделать следующее:

Реализовать механизм контроля отрицательных остатков, который бы, явно запрещал пользователю проводить документы, если товара нехватает по остаткам, это касается регистров накопления Остатки товаров на складах, остатки товаров переданных, остатки организаций, товары в нтт, и т.д. Для всех документов которые тем или иным образом списывают товар по этим регистрам нужно предусмотреть контроль. Можно предусмотреть также возможность выключения механизма в константах.

Пример общей функции контроля остатков:

Функция ПроверитьОстаткиНоменклатуры(СтруктураДанных) Экспорт

Остаток = 0;
СтруктураОтбора = Новый Структура();
Если СтруктураДанных.ОтражатьВУправленческомУчете И (Не СтруктураДанных.ОтражатьВБухгалтерскомУчете) И (Не СтруктураДанных.ОтражатьВНалоговомУчете) Тогда
СтруктураОтбора.Вставить(«Номенклатура», СтруктураДанных.Номенклатура);
Если СтруктураДанных.Номенклатура.ВестиУчетПоХарактеристикам Тогда
//Если СтруктураДанных.ХарактеристикаНоменклатуры Справочники.ХарактеристикиНоменклатуры.ПустаяСсылка() Тогда
СтруктураОтбора.Вставить(«ХарактеристикаНоменклатуры», СтруктураДанных.ХарактеристикаНоменклатуры);
//КонецЕсли;
КонецЕсли;
Если СтруктураДанных.Свойство(«Склад») Тогда
Если СтруктураДанных.Склад Неопределено И СтруктураДанных.Склад Справочники.Склады.ПустаяСсылка() Тогда
СтруктураОтбора.Вставить(«Склад», СтруктураДанных.Склад);
КонецЕсли;
ИначеЕсли СтруктураДанных.Свойство(«ДоговорКонтрагента») Тогда
Если СтруктураДанных.ДоговорКонтрагента Неопределено И СтруктураДанных.ДоговорКонтрагента Справочники.ДоговорыКонтрагентов.ПустаяСсылка() Тогда
СтруктураОтбора.Вставить(«ДоговорКонтрагента», СтруктураДанных.ДоговорКонтрагента);
КонецЕсли;
КонецЕсли;

Если СтруктураДанных.Свойство(«Склад») Тогда
ОстатокТовара = РегистрыНакопления.ТоварыНаСкладах.Остатки(СтруктураДанных.Дата,СтруктураОтбора,,»Количество»).Итог(«Количество»);
Если СтруктураДанных.Склад Неопределено И СтруктураДанных.Склад Справочники.Склады.ПустаяСсылка() Тогда
Если СтруктураДанных.Склад.ВидСклада = Перечисления.ВидыСкладов.НТТ Тогда
СтруктураОтбора.Вставить(«ЦенаВРознице», СтруктураДанных.Цена);
КонецЕсли;
КонецЕсли;
ОстатокТовараВНТТ = РегистрыНакопления.ТоварыВНТТ.Остатки(СтруктураДанных.Дата,СтруктураОтбора,,»Количество»).Итог(«Количество»);
Если Константы.УчитыватьРезервыПриКонтролеОстатков.Получить() Тогда
ОстатокТовараРезерв = РегистрыНакопления.ТоварыВРезервеНаСкладах.Остатки(СтруктураДанных.Дата,СтруктураОтбора,,»Количество»).Итог(«Количество»);
КонецЕсли;
Если Константы.УчитыватьРезервыПриКонтролеОстатков.Получить() Тогда
Остаток = ОстатокТовара+ОстатокТовараВНТТ- ОстатокТовараРезерв;
Иначе
Остаток = ОстатокТовара+ОстатокТовараВНТТ;
КонецЕсли;

Иначе
Остаток = РегистрыНакопления.ТоварыПереданные.Остатки(СтруктураДанных.Дата, СтруктураОтбора,,»Количество»).Итог(«Количество»);
КонецЕсли;

ИначеЕсли СтруктураДанных.ОтражатьВБухгалтерскомУчете И (СтруктураДанных.ОтражатьВНалоговомУчете ИЛИ СтруктураДанных.ОтражатьВУправленческомУчете) Тогда
Если СтруктураДанных.Свойство(«Склад») Тогда
СтруктураОтбора.Вставить(«Организация», СтруктураДанных.Организация);
СтруктураОтбора.Вставить(«Номенклатура», СтруктураДанных.Номенклатура);
Остаток = РегистрыНакопления.ТоварыОрганизаций.Остатки(СтруктураДанных.Дата, СтруктураОтбора,,»Количество»).Итог(«Количество»);
КонецЕсли;
КонецЕсли;

Возврат Остаток;

КонецФункции

В модуле документа, например пусть это будет перемещение товаров в обработке проведения будет примерно следующее:

//Проверим возможность проведения по остаткам тмц
Если НЕ Константы.ОтключитьКонтрольОстатковТМЦ.Получить() Тогда
Для Каждого СтрокаТовары Из Товары Цикл
//Сформируем структуру для проверки остатков
СтруктураДанных = Новый Структура();
СтруктураДанных.Вставить(«Дата»,?(ЭтоНовый(), ТекущаяДата(), Дата));
СтруктураДанных.Вставить(«Номенклатура»,СтрокаТовары.Номенклатура);
СтруктураДанных.Вставить(«Склад»,СкладОтправитель);
СтруктураДанных.Вставить(«ОтражатьВБухгалтерскомУчете», ОтражатьВБухгалтерскомУчете);
СтруктураДанных.Вставить(«ОтражатьВНалоговомУчете», ОтражатьВНалоговомУчете);
СтруктураДанных.Вставить(«ОтражатьВУправленческомУчете», ОтражатьВУправленческомУчете);
СтруктураДанных.Вставить(«ХарактеристикаНоменклатуры», СтрокаТовары.ХарактеристикаНоменклатуры);
СтруктураДанных.Вставить(«Организация», Организация);
СтруктураДанных.Вставить(«Цена», СтрокаТовары.Цена);
ОстатокНоменклатуры = ОбщегоНазначения.ПроверитьОстаткиНоменклатуры(СтруктураДанных);
Если (ОстатокНоменклатуры — СтрокаТовары.Количество) < 0 Тогда
Сообщить(«В строке «+СтрокаТовары.НомерСтроки+ » т.ч. товары недостаточно «+Число(-(ОстатокНоменклатуры-СтрокаТовары.Количество))+» «+СтрокаТовары.Номенклатура+» «+СтрокаТовары.ХарактеристикаНоменклатуры+ » для списания!»);
Отказ = Истина;
КонецЕсли;
Если СтрокаТовары.Количество < 0 Тогда
Сообщить(«В строке «+СтрокаТовары.НомерСтроки+ » указано недоступное значение количества»);
Отказ = Истина;
КонецЕсли;
КонецЦикла;
КонецЕсли;

Также для удобства пользователя, можно в форме документа вывести в колонку фактический остаток товаров, и отражать его при выводе строки:
//Сформируем структуру для проверки остатков
СтруктураДанных = Новый Структура();
СтруктураДанных.Вставить(«Дата»,?(ЭтоНовый(), ТекущаяДата(),Дата));
СтруктураДанных.Вставить(«Номенклатура»,ДанныеСтроки.Номенклатура);
СтруктураДанных.Вставить(«Склад»,СкладОтправитель);
СтруктураДанных.Вставить(«ОтражатьВБухгалтерскомУчете», ОтражатьВБухгалтерскомУчете);
СтруктураДанных.Вставить(«ОтражатьВНалоговомУчете», ОтражатьВНалоговомУчете);
СтруктураДанных.Вставить(«ОтражатьВУправленческомУчете», ОтражатьВУправленческомУчете);
СтруктураДанных.Вставить(«ХарактеристикаНоменклатуры», ДанныеСтроки.ХарактеристикаНоменклатуры);
СтруктураДанных.Вставить(«Организация», Организация);
СтруктураДанных.Вставить(«Цена», ДанныеСтроки.Цена);
ОформлениеСтроки.Ячейки.ФактическийОстатокОтправителя.Значение = ОбщегоНазначения.ПроверитьОстаткиНоменклатуры(СтруктураДанных);

Выровнять отрицательные остатки товаров по всем регистрам каким бы то ни было способом, или программным или документами инвентаризации-списания-оприходования. Можно также документом корректировка записей регистров, будьте осторожны при приходовании товара, возможно его действительно минус.

Настроить правильно параметры учета. Укажите списывать партии товаров при проведении документов и укажите метод списания ТМЦ фифо или лифо, если будет указано метод списания по средней, то про отчеты по прибыли можете забыть, они будут 100% некорректны. Проверьте остальные параметры учета.

Реализовать механизм контроля при проведении по партиям товаров.

Пример общих функций:

Функция ВыполнитьКонтрольОстатковПоПартиямУпр(Ссылка, ТаблицаДвижений) Экспорт

Если Ссылка.Товары.Количество() = 0 Тогда
Возврат Ложь;
КонецЕсли;

ОтказОтПроведения = Ложь;
Если ТипЗнч(Ссылка) = Тип(«ДокументСсылка.ОтчетКомиссионераОПродажах»)
ИЛИ ТипЗнч(Ссылка) = Тип(«ДокументСсылка.ВозвратТоваровОтПокупателя») Тогда
//контролируем остатки по партиям только в упр учете
Если (Ссылка.ОтражатьВУправленческомУчете И Не Ссылка.ОтражатьВБухгалтерскомУчете И Не
Ссылка.ОтражатьВНалоговомУчете) Тогда
ТаблицаДляЗапроса = «ПартииТоваровПереданные»;
ТаблицаСообщений = ОпределитьОстатокВернутьСообщение(ТаблицаДляЗапроса, Ссылка);
Для Каждого СтрСообщение Из ТаблицаСообщений Цикл
Сообщить(СтрСообщение.Сообщение);
ОтказОтПроведения = Истина;
КонецЦикла;
Иначе
Возврат Ложь;
КонецЕсли;
Иначе
Если (Ссылка.ОтражатьВУправленческомУчете И Не Ссылка.ОтражатьВБухгалтерскомУчете И Не
Ссылка.ОтражатьВНалоговомУчете) ИЛИ (Ссылка.ОтражатьВУправленческомУчете И
Ссылка.ОтражатьВБухгалтерскомУчете) Тогда
ТаблицаДляЗапроса = «ПартииТоваровНаСкладах»;
ТаблицаСообщений = ОпределитьОстатокВернутьСообщение(ТаблицаДляЗапроса, Ссылка);
Для Каждого СтрСообщение Из ТаблицаСообщений Цикл
Сообщить(СтрСообщение.Сообщение);
ОтказОтПроведения = Истина;
КонецЦикла;
ИначеЕсли (Не Ссылка.ОтражатьВУправленческомУчете И Ссылка.ОтражатьВБухгалтерскомУчете И
Ссылка.ОтражатьВНалоговомУчете) ИЛИ (Ссылка.ОтражатьВУправленческомУчете И
Ссылка.ОтражатьВНалоговомУчете) Тогда
ТаблицаДляЗапроса = «ПартииТоваровНаСкладахНалоговыйУчет»;
ТаблицаСообщений = ОпределитьОстатокВернутьСообщение(ТаблицаДляЗапроса, Ссылка);
Для Каждого СтрСообщение Из ТаблицаСообщений Цикл
Сообщить(СтрСообщение.Сообщение);
ОтказОтПроведения = Истина;
КонецЦикла;
ИначеЕсли Ссылка.ОтражатьВУправленческомУчете И Ссылка.ОтражатьВБухгалтерскомУчете И
Ссылка.ОтражатьВНалоговомУчете Тогда
ТаблицаДляЗапроса = «ПартииТоваровНаСкладах»;
ТаблицаСообщений = ОпределитьОстатокВернутьСообщение(ТаблицаДляЗапроса, Ссылка);
Для Каждого СтрСообщение Из ТаблицаСообщений Цикл
Сообщить(СтрСообщение.Сообщение);
ОтказОтПроведения = Истина;
КонецЦикла;
ТаблицаДляЗапроса = «ПартииТоваровНаСкладахНалоговыйУчет»;
ТаблицаСообщений = ОпределитьОстатокВернутьСообщение(ТаблицаДляЗапроса, Ссылка);
Для Каждого СтрСообщение Из ТаблицаСообщений Цикл
Сообщить(СтрСообщение.Сообщение);
ОтказОтПроведения = Истина;
КонецЦикла;

КонецЕсли;
КонецЕсли;

Возврат ОтказОтПроведения;

КонецФункции

Функция ОпределитьОстатокВернутьСообщение(ТаблицаДляЗапроса, Ссылка)
ТаблицаСообщений= Новый ТаблицаЗначений;
ТаблицаСообщений.Колонки.Добавить(«Сообщение»);
Таблица = Ссылка.Товары.Выгрузить();
Если ТипЗнч(Ссылка) = Тип(«ДокументСсылка.РеализацияТоваровУслуг») ИЛИ
ТипЗнч(Ссылка) = Тип(«ДокументСсылка.ОтчетОРозничныхПродажах»)Тогда
Таблица.Свернуть(«Номенклатура, ХарактеристикаНоменклатуры, Склад», «Количество»);
ИначеЕсли ТипЗнч(Ссылка) = Тип(«ДокументСсылка.ПеремещениеТоваров») ИЛИ
ТипЗнч(Ссылка) = Тип(«ДокументСсылка.ОтчетКомиссионераОПродажах») ИЛИ
ТипЗнч(Ссылка) = Тип(«ДокументСсылка.ВозвратТоваровОтПокупателя»)Тогда
Таблица.Свернуть(«Номенклатура, ХарактеристикаНоменклатуры», «Количество»);
КонецЕсли;
Для Каждого Строка Из Таблица Цикл

Запрос = Новый Запрос;
Запрос.Текст =
«ВЫБРАТЬ
| ВложенныйЗапрос.КоличествоОстаток — &КоличествоВДокументе КАК Разница
|ИЗ
| (ВЫБРАТЬ
| «+ТаблицаДляЗапроса+»Остатки.Номенклатура КАК Номенклатура,
| «+ТаблицаДляЗапроса+»Остатки.»+?(ТаблицаДляЗапроса =»ПартииТоваровПереданные»,»ДоговорКонтрагента Как ДоговорКонтрагента»,»Склад Как Склад»)+»,
| «+ТаблицаДляЗапроса+»Остатки.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
| СУММА(«+ТаблицаДляЗапроса+»Остатки.КоличествоОстаток) КАК КоличествоОстаток
| ИЗ
| РегистрНакопления.»+ТаблицаДляЗапроса+».Остатки(
| &Дата,
| Номенклатура = &Номенклатура
| «+?(ТаблицаДляЗапроса = «ПартииТоваровНаСкладах» ИЛИ ТаблицаДляЗапроса = «ПартииТоваровПереданные» ,?(Строка.Номенклатура.ВестиУчетПоХарактеристикам,»И ХарактеристикаНоменклатуры = &ХарактеристикаНоменклатуры»,»"),»И Организация = &Организация»)+»
| «+?(ТаблицаДляЗапроса =»ПартииТоваровПереданные»,»И ДоговорКонтрагента = &ДоговорКонтрагента»,»И Склад = &Склад»)+») КАК «+ТаблицаДляЗапроса+»Остатки
|
| СГРУППИРОВАТЬ ПО
| «+ТаблицаДляЗапроса+»Остатки.Номенклатура,
| «+ТаблицаДляЗапроса+»Остатки.»+?(ТаблицаДляЗапроса =»ПартииТоваровПереданные»,»ДоговорКонтрагента»,»Склад»)+»,
| «+ТаблицаДляЗапроса+»Остатки.ХарактеристикаНоменклатуры) КАК ВложенныйЗапрос»;

Запрос.УстановитьПараметр(«Дата», Ссылка.Дата);
Запрос.УстановитьПараметр(«КоличествоВДокументе», Строка.Количество);
Запрос.УстановитьПараметр(«Номенклатура», Строка.Номенклатура);
СообщениеСклад = «»;
Если ТипЗнч(Ссылка) = Тип(«ДокументСсылка.РеализацияТоваровУслуг») ИЛИ
ТипЗнч(Ссылка) = Тип(«ДокументСсылка.ОтчетОРозничныхПродажах»)Тогда
Запрос.УстановитьПараметр(«Склад», Строка.Склад);
СообщениеСклад = Строка.Склад;
ИначеЕсли ТипЗнч(Ссылка) = Тип(«ДокументСсылка.ПеремещениеТоваров») Тогда
Запрос.УстановитьПараметр(«Склад», Ссылка.СкладОтправитель);
СообщениеСклад = Ссылка.СкладОтправитель;
ИначеЕсли ТипЗнч(Ссылка) = Тип(«ДокументСсылка.ОтчетКомиссионераОПродажах») ИЛИ
ТипЗнч(Ссылка) = Тип(«ДокументСсылка.ВозвратТоваровОтПокупателя»)Тогда
Запрос.УстановитьПараметр(«ДоговорКонтрагента», Ссылка.ДоговорКонтрагента);
СообщениеСклад = Ссылка.ДоговорКонтрагента;
КонецЕсли;
Если ТаблицаДляЗапроса = «ПартииТоваровНаСкладах» ИЛИ ТаблицаДляЗапроса =»ПартииТоваровПереданные» Тогда
Если Строка.Номенклатура.ВестиУчетПоХарактеристикам Тогда
Запрос.УстановитьПараметр(«ХарактеристикаНоменклатуры», Строка.ХарактеристикаНоменклатуры);
КонецЕсли;
Иначе
Запрос.УстановитьПараметр(«Организация», Ссылка.Организация);
КонецЕсли;

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Количество() = 0 Тогда
СтрокаТабл = ТаблицаСообщений.Добавить();
СтрокаТабл.Сообщение = «»+?(ТаблицаДляЗапроса = «ПартииТоваровНаСкладах» ИЛИ ТаблицаДляЗапроса = «ПартииТоваровПереданные» , «Управленческий учет: «, «Налоговый учет: «)+»Для номенклатуры «+Строка.Номенклатура+ «: «+Строка.ХарактеристикаНоменклатуры+
?(ТаблицаДляЗапроса =»ПартииТоваровПереданные», «для контрагента «+Ссылка.Контрагент+» для договора «,» на складе «)+ СообщениеСклад +?(ТаблицаДляЗапроса «ПартииТоваровНаСкладах» И ТаблицаДляЗапроса «ПартииТоваровПереданные», » для организации «+Ссылка.Организация, «») +» не достаточно «+ (Строка.Количество)+
» шт для списания по партиям»;
КонецЕсли;

Пока Выборка.Следующий() Цикл
Если Выборка.Разница < 0 Тогда
СтрокаТабл = ТаблицаСообщений.Добавить();
СтрокаТабл.Сообщение = «»+?(ТаблицаДляЗапроса = «ПартииТоваровНаСкладах» ИЛИ ТаблицаДляЗапроса = «ПартииТоваровПереданные», «Управленческий учет: «, «Налоговый учет: «)+»Для номенклатуры «+Строка.Номенклатура+ «: «+Строка.ХарактеристикаНоменклатуры+
?(ТаблицаДляЗапроса =»ПартииТоваровПереданные»,»для контрагента «+Ссылка.Контрагент+» для договора «,» на складе «)+ СообщениеСклад +?(ТаблицаДляЗапроса «ПартииТоваровНаСкладах» И ТаблицаДляЗапроса «ПартииТоваровПереданные», » для организации «+Ссылка.Организация, «») +» не достаточно «+ (-Выборка.Разница)+
» шт для списания по партиям»;
КонецЕсли;

КонецЦикла;

КонецЦикла;

Возврат ТаблицаСообщений;

КонецФункции

Для непосредственного использования указанных функций вклиниваемся в процедуру ДвиженияПоРегистрам в модуле объекта документа, и пишем примерно следующее:

ПроводитьПоПартиям = РегистрыСведений.УчетнаяПолитика.ПолучитьПоследнее(Дата).СписыватьПартииПриПроведенииДокументов;
КонтролироватьСписаниеПартий = Не Константы.ОтключитьКонтрольОстатковПоПартиям.Получить();
Если ПроводитьПоПартиям Тогда
Если КонтролироватьСписаниеПартий Тогда
Отказ = УправлениеЗапасамиПартионныйУчет.ВыполнитьКонтрольОстатковПоПартиямУпр(Ссылка, Движения.СписанныеТовары.Выгрузить());
Если Не Отказ Тогда
УправлениеЗапасамиПартионныйУчет.ДвижениеПартийТоваров(Ссылка, Движения.СписанныеТовары.Выгрузить());
КонецЕсли;
Иначе
УправлениеЗапасамиПартионныйУчет.ДвижениеПартийТоваров(Ссылка, Движения.СписанныеТовары.Выгрузить());
КонецЕсли;
Иначе

// В неоперативном режиме границы последовательностей сдвигаются назад, если они позже документа.
Если РежимПроведения = РежимПроведенияДокумента.Неоперативный Тогда
УправлениеЗапасамиПартионныйУчет.СдвигГраницыПоследовательностиПартионногоУчетаНазад(Дата, Ссылка, Организация)
КонецЕсли;

КонецЕсли;

Данный код вставлен в существующий.

При контроле партий, кроме выдачи сообщения о нехватки по партиям товаров, в данном случае будет еще выдаваться сообщение-подсказка пользователю о том что товар якобы есть но в других разрезах, например с другой характеристикой, и в служебных сообщениях будет выдаваться остаток возможных позиций.

Далее после указанных манипуляций нужно привести в соответствие данные партионного учета с данными регистров остатков. Т.е. остатки по всем партиям суммарно должны соответствовать остаткам по регистрам остатков во всех разрезах как для товаров обычных так и товаров переданных, т.е. комиссионных. Данную операцию можно производить вручную, формируя отчеты и выравнивая партии документов корректировка записей регистров, а можно использовать обработку.

В архиве непосредственно файл обработки для выравнивания партий и два отчета созданных при помощи системы компоновки данных для контроля партий.

Сначала немного об обработке.
В общем случае на данный момент обработка умеет выравнивать партии по товарам, и товарам переданным в управленческом учете при условии что учет ведется не более чем по доп характеристикам номенклатуры. При установке соответствующих флагов обработка попытается выполнить сначала простое перемещение партий по складам или договорам (в случае товаров переданных), затем выполнит пересорт по доп характеристикам, в последствии спишет лишнее, и дооприходует недостачи. Так же в обработке не предусмотрен момент когда товар с остатком минус, глупо выравнивать партии товаров если что-то неправильно с самом учете товаров. Все это записывается четырьмя документами корректировка записей регистров, с комментариями. Дата у документов корректировки текущая, поэтому не думайте что после выполнения обработки можно будет безпроблемно перепроводить документы предыдущих периодов, для них все останется все также плохо. Так же не рекомендуется перепроводить документы предыдущих периодов, но если уж все-таки так случилось, то возможно партии у вас снова поплывут, и прийдется снова запускать обработку.

Отчеты. Два отчета для контроля по партиям товаров и контроля партий переданных товаров. По сути если отчеты формируются пустые значит по партиям все отлично, если нет, то решайте сами как вы будете их выравнивать, толи в ручную, толи обработкой.

Купить
0 оценок
Цена: 2 400 руб.
Вход