Дополнение
У нас цена реализации зависит от даты. Мы хотим, чтобы при изменении даты документа цены в строках документа соответственно менялись;
Процедура ДатаДок()
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
Если Сорт.Выбран()=1 Тогда
Цена=Окр(Товар.ЦенаР.Получить(ДатаДок)*(Сорт.Процент/100),2,1);
Сумма=Окр(КолО*Цена,2,1);
Иначе
Цена=0;
Сумма=0;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Процедура простая и в комментариях не нуждается
При заполнении накладной нам надо помнить, чего сколько на каком складе у нас лежит. В 1С для такой ситуации есть специальный механизм подбора. Реализуем его в нашей расходной накладной. Но сперва, для подбора, создадим особую форму списка справочника товаров.
Функция Ост()
ТекТовар=ТекущийЭлемент();
// Получаем текущий товар в строке
КолТов=Регистр.ОстаткиТоваров.СводныйОстаток(Склад,
ТекущийЭлемент(),,,"Количество");
// Получаем суммарный остаток по ресурсу "Количество"
// по измерениям "Склад" и "Товар", по остальным измерениям суммируем
Если КолТов<=0 Тогда
Возврат("");
// если товара на складе нет в поле Ост вернем пустую строку
Иначе
Возврат(КолТов);
// иначе вернем количество остатка
КонецЕсли;
КонецФункции
Процедура Подбор()
// Эта процедура запускается по нажатию кнопки [Подбор]
ОткрытьПодбор("Номенклатура","ДляПодбора");
// Инициализируем механизм подбора и указываем, что подбирать мы
// будем из справочника Номенклатура, используя форму списка "ДляПодбора"
УстановитьЗначениеВПодборе("Склад",Склад);
// В форму подбора в поле "Склад" передаем значение склада из
// текущего документа
КонецПроцедуры
//-----------------------------------------------
Процедура ОбработкаПодбора(ВыбТов)
// Предопределенная процедура, срабатывающая по событию – выбор
// элемента ВыбТов из справочника
КолОст=Регистр.ОстаткиТоваров.СводныйОстаток(Склад,
ВыбТов,,,"Количество");
// Проверим остаток
Если КолОст<=0 Тогда
Возврат;
// если остаток на складе отсутствует, завершаем процедуру
КонецЕсли;
ТабЗн1=СоздатьОбъект("ТаблицаЗначений");
// временная динамическая таблица
ТабЗн2=СоздатьОбъект("ТаблицаЗначений");
// еще одна временная динамическая таблица
ТабЗн2.НоваяКолонка("Сорт","Справочник.Сорт",,,"Сорт",5);
ТабЗн2.НоваяКолонка("Остаток","Число",17,2,"Остаток",17);
// колонки д. таблицы
РегО=СоздатьОбъект("Регистр.ОстаткиТоваров");
РегО.УстановитьФильтр(Склад,ВыбТов);
// в копии регистра остатков нас будут интересовать
// итоги по конкретному складу и конкретному товару
РегО.ВыгрузитьИтоги(ТабЗн1,1,1);
// перегрузим итоги в д. таблицу
РегО="";
ТабЗн1.ВыбратьСтроки();
Пока ТабЗн1.ПолучитьСтроку()=1 Цикл
Ост=ТабЗн1.Количество;
Если Ост>0 Тогда // есть что проверять
// если есть остаток, мы его перенесем во вторую д. таблицу
Срт=ТабЗн1.Сорт;
ТабЗн2.НоваяСтрока();
ТабЗн2.Сорт=Срт;
ТабЗн2.Остаток=Ост;
КонецЕсли;
КонецЦикла;
ТабЗн2.Свернуть("1","2");
// просуммируем по сортам и получим количество товара по каждому сорту
ВыбСтрока=1;
Если ТабЗн2.ВыбратьСтроку(ВыбСтрока,
СокрЛП(ВыбТов.Код)+" ("
+СокрЛП(ВыбТов.Наименование)+")")=1 Тогда
// Выберем строку с нужным сортом
НоваяСтрока();
// создаем в документе новую строку
Товар=ВыбТов;
// заполняем поле "Товар"
СортВыб=ТабЗн2.ПолучитьЗначение(ВыбСтрока,"Сорт");
// по выбранной строке получаем сорт
КолОст=ТабЗн2.ПолучитьЗначение(ВыбСтрока,"Остаток");
// и остаток
Сорт=СортВыб;
СпрЕд=СоздатьОбъект("Справочник.Единицы");
СпрЕд.ИспользоватьВладельца(Товар);
СпрЕд.ВыбратьЭлементы();
Пока СпрЕд.ПолучитьЭлемент()=1 Цикл
Если СпрЕд.Ед=Товар.ЕдИзм Тогда
Ед=СпрЕд.ТекущийЭлемент();
Прервать;
КонецЕсли;
КонецЦикла;
// это уже было...
Цена=Окр(Товар.ЦенаР.Получить(ДатаДок)*(Сорт.Процент/100),2,1);
КолВыб=0;
Если ВвестиЧисло(КолВыб,СокрЛП(ВыбТов.Код)
+"/"+СокрЛП(Строка(СортВыб)+" кол:"
+Строка(КолОст)),8,2,0)=1 Тогда
// Введем нужное нам количество
Если КолВыб>КолОст Тогда
// сравним введенное нами количество с остатком
КолВыб=КолОст;
КонецЕсли;
Кол=КолВыб;
КолО=Окр(Кол*(Ед.Коэффициент),2,1);
Сумма=Окр(КолО*Цена,2,1);
КонецЕсли;
АктивизироватьСтроку();
// установим курсор в документе на строку, которую мы ввели
КонецЕсли;
КонецПроцедуры
Процедура ОбработкаПроведения()
РегОст=СоздатьОбъект("Регистр.ОстаткиТоваров");
Если СравнитьТА()=-1 Тогда
// Проверяем, не проводится ли документ ранее точки актуальности итогов
РегОст.ВременныйРасчет(1);
РассчитатьРегистрыНа(ТекущийДокумент());
КонецЕсли;
// Проверка на наличие на остатке
ВыбратьСтроки();
ФлагОтказа=0;
Пока (ПолучитьСтроку()>0) Цикл
Остат=РегОст.СводныйОстаток(Склад,Товар,Сорт,,"Количество");
Если Остат
Сообщить("Нет товара № "
+СокрЛП(Товар.Код)+"/"
+СокрЛП(Сорт.Наименование)+" в колич. "
+КолО+" (имеется "+Остат+")");
ФлагОтказа=1;
КонецЕсли;
КонецЦикла;
// аналогичную часть кода см. в отчете ОстаткиНаСкладе
Если ФлагОтказа=1 Тогда
НеПроводитьДокумент();
Возврат;
КонецЕсли;
// Это см. документы Приход/Расход денег
// По регистру взаиморасчетов
Регистр.Взаиморасчеты.Контрагент = Покупатель;
Регистр.Взаиморасчеты.Договор = Договор;
Регистр.Взаиморасчеты.Сумма = Итог("Сумма");
Регистр.Взаиморасчеты.ФлагДвижения = 2;
Регистр.Взаиморасчеты.ДвижениеРасходВыполнить();
Если Константа.МетодСписания=Перечисление.МетодСписания.ФИФО Тогда
// Здесь будет записана методика списания по FIFO
ИначеЕсли Константа.МетодСписания=Перечисление.МетодСписания.ЛИФО
Тогда
// Здесь будет записана методика списания по LIFO
ИначеЕсли
Константа.МетодСписания=Перечисление.МетодСписания.По_среднему
Тогда
// Здесь будет записана методика списания по-среднему
КонецЕсли;
КонецПроцедуры
// Здесь будет записана методика списания по FIFO
ТабЗн1=СоздатьОбъект("ТаблицаЗначений");
// временная таблица
ТабЗн2=СоздатьОбъект("ТаблицаЗначений");
// еще одна временная таблица
ТабЗн2.НоваяКолонка("Партия","Документ.ПриходнаяНакладная");
ТабЗн2.НоваяКолонка("КоличествоП","Число",14,2);
ТабЗн2.НоваяКолонка("СуммаП","Число",19,2);
ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
КолВыб=КолО;
РегОст.УстановитьФильтр(Склад,Товар,Сорт);
РегОст.ВыгрузитьИтоги(ТабЗн1,1,1);
// см. операцию подбора
ТабЗн1.Свернуть("4","5,6");
// а здесь интересно: Структура ТабЗн1 после выгрузки будет аналогична
// структуре регистра. Реквизит "Партия" в регистре стоит на 4-ой
// позиции, значит и колонка "Партия" – 4-ая, Колонки "Количество"
// и "СуммаП" – соответственно 5-ая и 6-ая
ТабЗн1.ВыбратьСтроки();
Пока ТабЗн1.ПолучитьСтроку()=1 Цикл
Прт=ТабЗн1.Партия;
Ост=ТабЗн1.Количество;
Сум=ТабЗн1.СуммаП;
Если Ост>0 Тогда // есть что проверять
ТабЗн2.НоваяСтрока();
ТабЗн2.Партия=Прт;
ТабЗн2.КоличествоП=Ост;
ТабЗн2.СуммаП=Сум;
КонецЕсли;
КонецЦикла;
// Заполняем промежуточную таблицу
ТабЗн1.Очистить();
// Удаляем все записи и колонки из ТабЗн1
ТабЗн2.Сортировать("1+",1);
// Сортируем по документам в порядке возрастания даты (FIFO)
// Более ранние партии вверху
ТабЗн2.ВыбратьСтроки();
Пока ТабЗн2.ПолучитьСтроку()=1 Цикл
Ост=ТабЗн2.КоличествоП;
Сум=ТабЗн2.СуммаП;
ЦенаПП=Окр(Сум/Ост,2,1);
// определяем цену текущей партии
Парт=ТабЗн2.Партия;
// а вот и сама партия
Если КолВыб>Ост Тогда // Ост
// требуемое количество больше, чем остатки в текущей партии,
// здесь спишем сколько есть, а что осталось, из более поздней
// партии
Регистр.ОстаткиТоваров.Склад = Склад;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = Парт;
Регистр.ОстаткиТоваров.Количество = Ост;
Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенаПП*Ост,2,1);
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*Ост,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 1;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
// Про обороты не забыть!
Регистр.ОборотыТоваров.Склад = Склад;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = Ост;
Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенаПП*Ост,2,1);
Регистр.ОборотыТоваров.ФлагДвижения = 1;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
КолВыб=КолВыб-Ост;
// это сколько остатков нам не хватает до полного счастья
Иначе
// В партии товара больше, чем мы запрашиваем.
// Списываем сколько запрашиваем
Если КолВыб>0 Тогда // КолВыб
Регистр.ОстаткиТоваров.Склад = Склад;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = Парт;
Регистр.ОстаткиТоваров.Количество = КолВыб;
Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенаПП*КолВыб,2,1);
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*КолВыб,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 1;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
Регистр.ОборотыТоваров.Склад = Склад;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = КолВыб;
Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенаПП*КолВыб,2,1);
Регистр.ОборотыТоваров.ФлагДвижения = 1;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
КолВыб=КолВыб-Ост;
КонецЕсли;
КонецЕсли;
КонецЦикла;
ТабЗн2.УдалитьСтроки();
// удаляем строки из временной таблицы.
// Готовим ее под следующую строку документа
КонецЦикла;
Здесь мы воспользовались для определения партий механизмом прямой выгрузки данных из регистра в таблицу значений.
ТабЗн2.Сортировать("1+",1);
На ТабЗн2.Сортировать("1-",1);
// Сортировка документов по убывающей. Последний – сверху
Но мы легких путей не ищем! Воспользуемся механизмом запроса.
// Здесь будет записана методика списания по LIFO
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
КолСпис=КолО;
Запрос="";
ТекстЗапроса="";
Если ИтогиАктуальны()=0 Тогда
ТекстЗапроса="
|Период с ДатаДок по ДатаДок;";
КонецЕсли;
ТекстЗапроса=ТекстЗапроса+"
|РегСклад=Регистр.ОстаткиТоваров.Склад;
|РегТовар=Регистр.ОстаткиТоваров.Товар;
|РегСорт=Регистр.ОстаткиТоваров.Сорт;
|РегПартия=Регистр.ОстаткиТоваров.Партия;
|РегКолич=Регистр.ОстаткиТоваров.Количество;
|РегСумма=Регистр.ОстаткиТоваров.СуммаП;
|Группировка РегПартия Упорядочить по РегПартия.ДатаДок;
|Функция КолКонОст=КонОст(РегКолич);
|Функция СумКонОст=КонОст(РегСумма);
|Условие (РегСклад=Склад);
|Условие (РегТовар=Товар);
|Условие (РегСорт=Сорт);";
Запрос=СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
Сообщить("Документ не проведен");
НеПроводитьДокумент();
Возврат;
КонецЕсли;
Пока Запрос.Группировка("РегПартия",-1)=1 Цикл
// В методе Группировка флаг – 1 указывает, что сортировка по запросу
// идет в порядке убывания. Более поздние документы идут первыми
Если КолСпис=0 Тогда
Прервать;
КонецЕсли;
ПартияСписания=Запрос.РегПартия;
Если Запрос.КолКонОст>КолСпис Тогда
Списывать=КолСпис;
Стоимость=Окр((Запрос.СумКонОст/Запрос.КолКонОст)*Списывать,2,1);
ИначеЕсли Запрос.КолКонОст=КолСпис Тогда
Списывать=КолСпис;
Стоимость=Запрос.СумКонОст;
ИначеЕсли Запрос.КолКонОст
Списывать=Запрос.КолКонОст;
Стоимость=Запрос.СумКонОст;
КонецЕсли;
КолСпис=КолСпис-Списывать;
Регистр.ОстаткиТоваров.Склад = Склад;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = ПартияСписания;
Регистр.ОстаткиТоваров.Количество = Списывать;
Регистр.ОстаткиТоваров.СуммаП = Стоимость;
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*Списывать,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 1;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
Регистр.ОборотыТоваров.Склад = Склад;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = Списывать;
Регистр.ОборотыТоваров.СуммаУ = Стоимость;
Регистр.ОборотыТоваров.ФлагДвижения = 1;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
КонецЦикла;
КонецЦикла;
// Здесь будет записана методика списания по-среднему
ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
КолОст=РегОст.СводныйОстаток(Склад,Товар,Сорт,,"Количество");
// Получаем суммарный остаток по указанным измерениям
// по данному ресурсу
СумОст=РегОст.СводныйОстаток(Склад,Товар,Сорт,,"СуммаП");
ЦенОст=Окр(СумОст/КолОст,2,1);
Парт=ПолучитьПустоеЗначение("Документ.ПриходнаяНакладная");
// А это, что-бы заполнить хоть чем-нибудь измерение "Партия"
Регистр.ОстаткиТоваров.Склад = Склад;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = Парт;
Регистр.ОстаткиТоваров.Количество = КолО;
Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенОст*КолО,2,1);
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*КолО,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 1;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
Регистр.ОборотыТоваров.Склад = Склад;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = КолО;
Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенОст*КолО,2,1);
Регистр.ОборотыТоваров.ФлагДвижения = 1;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
КонецЦикла;
2.23 Расходная накладная. Продолжение.
Документ " Расходная накладная" создан! Давайте проверим его в работе. И посмотрим, как у нас будет списываться товар при разных способах.
2.24 Накладная на перемещение.
Документ "Накладная на перемещение между складами" совместит в себе часть черт приходной и расходной накладных. Для простоты, в накладной на перемещение будет указана в качестве цены – цена поступления товара из справочника. Контрагента в ней не будет, следовательно не будет движений по регистру "Взаиморасчеты". Зато по каждому из оставшихся регистров движения будут двойные: по одному складу и по другому. Нумерация накладной будет совместная с расходными. И еще введем такой механизм, как ввод на основании. Он будет заключаться в возможности взяв приходную накладную, ее содержимым автоматически заполнить накладную на перемещение. Накладная будет располагаться в журнале накладных. Сведем все данные по документу а таблицу:
Идентификатор: НакладнаяНаПеремещение Журнал: Накладные Нумератор: Накладные Периодичность: Длина: Тип: Уникальность: Автонумерация: да Оперативный учет: да Может являться основанием для документа любого вида?: нет |