"Партионный учет"
Я работаю в фармацевтической фирме, где при оформлению документов на отгрузку товара требуется указывать цену завода-изготовителя. Если при поступлении новой партии такого товара, предыдущая партия еще не закончилась и цены поступления отличаются, то при учете такого товара возникают некоторые сложности. Ведение нескольких карточек для одного наименования товара часто затруднительно, т.к. , во-первых, при большом ассортименте и движении справочник очень быстро распухает и в нем появляется большое количество дублирующих строк, и, во-вторых, увеличиваются сами базы, что приводит к замедлению работы системы. Аналогичная проблема может возникнуть при создании конфигураций для ИЧП или для решения вопросов сертификации и в других случаях, когда требуется точно знать из какой партии продается товар.
Первая мысль, которая пришла мне в голову - это использование подчиненного справочника. Но когда я рассмотрел конфигурацию для ИЧП Александра Зданевича (размещена на Dev Page), его идея подошла для решения этой проблемы оптимально. Идея заключается в использовании регистра "Товарный запас". Незначительно переработав идею Александра Зданевича и с его согласия я публикую то решение.
Итак регистр "Товарный запас" у нас состоит из следующих компонентов:
Измерения: Товар (справочник товаров), Склад (справочник склады), Серия (число 8.2), Отгружено (Булево)
Ресурсы: Количество (число 7.0)
Реквизиты: Цена(число 8.2) , Сумма (число 10.2) - Это для упрощения формирования отчетов. Суммовой учет ведется на отдельных регистрах ("Средние цены" и "ФИФО")
В качестве номера серии будет использоваться цена прихода. У Александра Зданевича использовался номер приходной накладной. Можно использовать и номер серии товара, тогда при приходовании товара потребуется каждой серии отводить отдельную строку.
В приходных и расходных документах, в табличной части добавляем значение "Серия". В Модуле приходных документов прописываем движение по регистру "Товарный запас" следующим образом:
Регистр.ТоварныйЗапас.Товар=Товар;
Регистр.ТоварныйЗапас.Количество=Количество;
Регистр.ТоварныйЗапас.Цена=Цена;
Регистр.ТоварныйЗапас.Сумма=Сумма;
Регистр.ТоварныйЗапас.Отгружен=Перечисление.Булево.Да;
Если Товар.Партионный=Да Тогда
....Регистр.ТоварныйЗапас.Серия=Цена;
Иначе
....Регистр.ТоварныйЗапас.Серия=0;
КонецЕсли;
Регистр.ТоварныйЗапас.ДвижениеПриходВыполнить();
В конфигурации предусмотрено, что не для всех товаров ведется партионный учет. Товар имеет свойство "Партионный", имеющее тип "Булево".
При выписывании расходных документов в процедурах "Подбор", "Изменение товара" и пр. вставляет процедуру "Партия(Товар,Склад)" следующего вида
Процедура
Партия(Тов,Скл)
Список=СоздатьОбъект("СписокЗначений");
Запрос =
СоздатьОбъект("Запрос");
Рег=СоздатьОбъект("Регистр.ТоварныйЗапас");
ТекстЗапроса =
"//{{ЗАПРОС(Отчет)
|Склад =
Регистр.ТоварныйЗапас.Склад;
|Товар =
Регистр.ТоварныйЗапас.Товар;
|Партия =
Регистр.ТоварныйЗапас.Серия;
|КолВо =
Регистр.ТоварныйЗапас.Количество;
|Группировка Товар упорядочить по
Товар.Наименование без групп;
|Группировка Партия;
|Функция Ост = КонОст(КолВо);
|Условие(Товар=Тов);
|Условие(Склад=Скл);
|"//}}ЗАПРОС
;
// Если ошибка в запросе, то выход из
процедуры
Если
Запрос.Выполнить(ТекстЗапроса) = 0
Тогда
....Возврат;
КонецЕсли;
Пока
Запрос.Группировка("Товар") = 1
Цикл
....Пока
Запрос.Группировка("Партия") = 1
Цикл
....Если Запрос.Ост>0 Тогда
........Список.ДобавитьЗначение(Запрос.Партия,"Товар="+Товар+"
Серия="+СокрЛП(Запрос.Партия)+"
КолВо="+Запрос.Ост);
....КонецЕсли;
....КонецЦикла;
КонецЦикла;
Выб=Список.ВыбратьЗначение(ВыбПар,"Выберите
партию",,,0);
Список.ТекущаяСтрока(1);
Если Выб=1 Тогда
....Коли=Рег.СводныйОстаток(Товар,Склад,ВыбПар,,"Количество");
....Серия=ВыбПар;
Иначе
....Если Список.РазмерСписка()=0 Тогда
........Сигнал();
........Предупреждение("Данный
товар ни разу не приходывался",0);
....КонецЕсли;
....Предупреждение("Нет данного
товара на складе",0);
....Возврат;
КонецЕсли;
КонецПроцедуры
Это позволяет заполнить колонку "Серия" в расходном документе по выбору оператора из любых неизрасходованных партий. Проверка количества списываемого товара прямо в этой процедуре вряд-ли целесообразна, т.к. количество можно изменить и непосредственно в ячейке таблицы документа. Ее наверно удобней разместить в Модуле. Кусок кода модуля документа, отвечающий за проверку доступного количества товара на складе приведен ниже:
ВыбратьСтроки();
Пока( ПолучитьСтроку()>0) Цикл
........ (все необходимые проверки на Товар.Выбран() и пр.)
Ост=Рег.СводныйОстаток(Товар,Склад,Серия,,"Количество");
Если Количество>Ост Тогда
....Предупреждение("На складе нет
нужного количества товара "
....+Товар.Наименование + ". На
складе осталось "+Ост
....+" "+Товар.ЕдИзм+". Счет ╧
"+НомерДок
....+" от "+ДатаДок+" не
проводится!!!");
....НеПроводитьДокумент();
....Возврат;
КонецЕсли;
Регистр.ТоварныйЗапас.Товар=Товар;
Регистр.ТоварныйЗапас.Количество=Количество;
Регистр.ТоварныйЗапас.Цена=Цена;
Регистр.ТоварныйЗапас.Сумма=Сумма;
Регистр.ТоварныйЗапас.Склад=Склад;
Регистр.ТоварныйЗапас.Серия=Серия;
Если
Док.Отгружен=Перечисление.Булево.Да
Тогда
....Регистр.ТоварныйЗапас.Отгружен=Перечисление.Булево.Да;
Иначе
....Регистр.ТоварныйЗапас.Отгружен=Перечисление.Булево.Нет;
КонецЕсли;
Регистр.ТоварныйЗапас.ДвижениеРасходВыполнить();