Любителей футбола
просим не беспокоится. Речь у нас пойдет не о FIFA, а о способах
списания товара при разных системах учета. Бухгалтерам объяснять,
что это такое, не нужно. Для остальных кратенько поясним.
FIFO (First Input First Output)
– это такая система, при которой ранее пришедшие партии товара списываются
первыми. Цена списания – цена партии товара из которой списывают
товар.
LIFO (Last Input First Output)
– а это такая система, при которой последняя пришедшая партия товара
списывается в первую очередь. Цена списания – цена партии товара
из которой списывают товар.
По-среднему – здесь вообще партии не нужны. Цена списания
– средняя цена остатка партий товара на складе.
Мы должны при начале работы указать, какой системой списания мы
будем в дальнейшем пользоваться. Перечень возможных систем учета
мы будем держать в перечислении.
Процедура ПриНачалеРаботыСистемы()
// предопределенная процедура, запускается
при начале работы
// в 1С:Предприятии
  Перем Значение;
// Объявляем переменную
  Если Константа.МетодСписания.Выбран()=0
Тогда
// если константа не заполнена
    Рез=ВвестиЗначение(Значение,"Выберите
способ списания","Перечисление.МетодСписания");
// просим выбрать способ списания. Рез=1,
если выбор произведен,
// 0 – если нет
    Если Рез=1 Тогда
      Константа.МетодСписания=Значение;
// установим константе выбранное значение
    Иначе
      СтатусВозврата(0);
// Мы просили выбрать значение, а Вы
этого не сделали.
// С 1С работать не будете!
// СтатусВозврата определяет, как должно завершиться событие вызвавшее
// предопределенную процедуру. В данном случае открытие системы
должно
// завершиться неудачей. Т.е. 1С:Предприятие закроется.
    КонецЕсли;
  КонецЕсли;
КонецПроцедуры
У нас на одном
из складов есть некоторое количество товара. Пришло время создать
расходную накладную. Во многом она у нас будет повторять приходную.
Похожий набор полей шапки, только вместо поля "Поставщик" мы введем
поле "Покупатель". Номер документа у нас будет зависеть не от бухгалтерии
контрагента, а от нашей. Нам еще надо учесть, что будет позднее
создана накладная на перемещение, и у расходных накладных и у накладных
на перемещение должна быть общая нумерация. Это решается введением
Нумератора.
Расходная
накладная будет располагаться в уже существующем журнале "Накладные".
Данные по документу расходная накладная сведем в таблицу:
Идентификатор: РасходнаяНакладная Журнал: Накладные Нумератор: Накладные     Периодичность: Длина:        Тип: Уникальность:       Автонумерация: да Оперативный учет: да Может являться основанием для документа любого вида?: |
|||
Является основанием для |
Вводится на основании |
||
Шапка |
|||
Реквизит |
Описание |
ТипЗначения |
Доп. |
Покупатель |
Кому ушел товар |
С.Контрагенты |
|
Договор |
Основание отгрузки товара |
С.Договора |
|
Склад |
Откуда отгрузили товар |
С.Склады |
|
Таблица |
|||
Реквизит |
Описание |
ТипЗначения |
Доп. |
Товар |
Товар |
С.Номенклатура |
|
Сорт |
Сорт товара |
С.Сорт |
|
Кол |
Количество в произвольной ед. измерения |
Число 8.2 |
+ |
Ед |
Единица измерения |
С.Единицы |
|
КолО |
Количество в основной ед. измерения |
Число 8.2 |
+,И |
Цена |
Цена реализации |
Число 7.2 |
+ |
Сумма |
Сумма документа |
Число 15.2 |
+,И |
У нас цена реализации зависит от даты. Мы хотим, чтобы при изменении даты документа цены в строках документа соответственно менялись;
Процедура ДатаДок()
  ВыбратьСтроки();
  Пока ПолучитьСтроку()=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.УдалитьСтроки();
// удаляем строки из временной таблицы.
// Готовим ее под следующую строку документа
КонецЦикла;
Здесь мы воспользовались для определения партий
механизмом прямой выгрузки данных из регистра в таблицу значений. // Здесь будет записана методика списания
по 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;
  Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
  Регистр.ОборотыТоваров.ДвижениеВыполнить();
КонецЦикла;
Документ "Расходная
накладная" создан! Давайте проверим его в работе. И посмотрим, как
у нас будет списываться товар при разных способах.
Документ "Накладная
на перемещение между складами" совместит в себе часть черт приходной
и расходной накладных. Для простоты, в накладной на перемещение
будет указана в качестве цены – цена поступления товара из справочника.
Контрагента в ней не будет, следовательно не будет движений по регистру
"Взаиморасчеты". Зато по каждому из оставшихся регистров движения
будут двойные: по одному складу и по другому. Нумерация накладной
будет совместная с расходными. И еще введем такой механизм, как
ввод на основании. Он будет заключаться в возможности взяв приходную
накладную, ее содержимым автоматически заполнить накладную на перемещение.
Накладная будет располагаться в журнале накладных. Сведем все данные
по документу а таблицу:
Идентификатор: НакладнаяНаПеремещение Журнал: Накладные Нумератор: Накладные     Периодичность: Длина:         Тип: Уникальность:       Автонумерация: да Оперативный учет: да Может являться основанием для документа любого вида?: нет |
|||
Является основанием для |
Вводится на основании |
||
ПриходнаяНакладная |
|||
Шапка |
|||
Реквизит |
Описание |
ТипЗначения |
Доп. |
СкладО |
Склад отправитель |
С.Склады |
|
СкладП |
Склад получатель |
С.Склады |
|
Таблица |
|||
Реквизит |
Описание |
ТипЗначения |
Доп. |
Товар |
Товар |
С.Номенклатура |
|
Сорт |
Сорт товара |
С.Сорт |
|
Кол |
Количество в произвольной ед. измерения |
Число 8.2 |
+ |
Ед |
Единица измерения |
С.Единицы |
|
КолО |
Количество в основной ед. измерения |
Число 8.2 |
+,И |
Цена |
Цена учета |
Число 7.2 |
+ |
Сумма |
Сумма документа |
Число 15.2 |
+,И |
Процедура ВводНаОсновании(ДокОсн)
// предопределенная процедура. ДокОсн
– ссылка на документ,
// на основании которого мы хотим ввести текущий
// если мы хотим, чтобы и в дальнейшем эти документы
// были между собой связаны, надо в документе, вводимом на
// основании завести реквизит типа документа основания
// и сохранять там эту ссылку
  Если ДокОсн.Проведен()<>1 Тогда
// Если документ основание не проведен
// мы не можем ввести на его основании никакой документ
    Предупреждение("Приходная накладная
№ "+Строка(ДокОсн.НомерДок) +"
                |    от
"+Строка(ДокОсн.ДатаДок)+"
                |    не
проведена!");
    СтатусВозврата(0);
  КонецЕсли;
  ДатаДок=РабочаяДата();
// копируем реквизиты шапки
  СкладО=ДокОсн.Склад;
  СкладП="";
  Пока ДокОсн.ПолучитьСтроку()=1 Цикл
// копируем содержимое строк
    НоваяСтрока();
    Товар=ДокОсн.Товар;
    Сорт=ДокОсн.Сорт;
    Кол=ДокОсн.Кол;
    Ед=ДокОсн.Ед;
    КолО=ДокОсн.КолО;
    Цена=Товар.ЦенаП.Получить(ДатаДок);
    Сумма=Окр(КолО*Цена,2,1);
  КонецЦикла;
КонецПроцедуры
Процедура ОбработкаПроведения()
  РегОст=СоздатьОбъект("Регистр.ОстаткиТоваров");
  Если СравнитьТА()=-1 Тогда
    РегОст.ВременныйРасчет(1);
    РассчитатьРегистрыНа(ТекущийДокумент());
  КонецЕсли;
// Проверка на наличие на остатке
  ВыбратьСтроки();
  ФлагОтказа=0;
  Пока (ПолучитьСтроку()>0) Цикл
    Остат=РегОст.СводныйОстаток(СкладО,Товар,Сорт,,"Количество");
    Если Остат<КолО Тогдаbr>       Сообщить("Нет
товара № "+СокрЛП(Товар.Код)+"/"
              +СокрЛП(Сорт.Наименование)+"
в колич. "
              +КолО+" (имеется "+Остат+")");
      ФлагОтказа=1;
    КонецЕсли;
  КонецЦикла;
  Если ФлагОтказа=1 Тогда
    НеПроводитьДокумент();
    Возврат;
  КонецЕсли;
  Если Константа.МетодСписания=Перечисление.МетодСписания.ФИФО
Тогда
// Здесь будет записана методика списания
по FIFO
    ВыбратьСтроки();
    Пока ПолучитьСтроку()=1 Цикл
      КолСпис=КолО;
      Запрос="";
      ТекстЗапроса="";
      Если ИтогиАктуальны()=0 Тогда
        ТекстЗапроса="
        |Период
с ДатаДок по ДатаДок;";
      КонецЕсли;
      ТекстЗапроса=ТекстЗапроса+"
      |РегСклад=Регистр.ОстаткиТоваров.Склад;
      |РегТовар=Регистр.ОстаткиТоваров.Товар;
      |РегСорт=Регистр.ОстаткиТоваров.Сорт;
      |РегПартия=Регистр.ОстаткиТоваров.Партия;
      |РегКолич=Регистр.ОстаткиТоваров.Количество;
      |РегСумма=Регистр.ОстаткиТоваров.СуммаП;
      |Группировка РегПартия Упорядочить по РегПартия.ДатаДок;
      |Функция КолКонОст=КонОст(РегКолич);
      |Функция СумКонОст=КонОст(РегСумма);
      |Условие (РегСклад=СкладО);
      |Условие (РегТовар=Товар);
      |Условие (РегСорт=Сорт);";
      Запрос=СоздатьОбъект("Запрос");
      Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
        Сообщить("Документ не проведен");
        НеПроводитьДокумент();
        Возврат;
      КонецЕсли;
      Пока Запрос.Группировка("РегПартия",1)=1 Цикл
// Сортируем группировку по возрастанию
        Если КолСпис=0 Тогда
          Прервать;
        КонецЕсли;
        ПартияСписания=Запрос.РегПартия;
        Если  Запрос.КолКонОст>КолСпис Тогда
          Списывать=КолСпис;
          Стоимость=Окр((Запрос.СумКонОст/Запрос.КолКонОст)
          *Списывать,2,1);
        ИначеЕсли Запрос.КолКонОст=КолСпис Тогда
          Списывать=КолСпис;
          Стоимость=Запрос.СумКонОст;
        ИначеЕсли Запрос.КолКонОст<КолСпис Тогдаbr>
          Списывать=Запрос.КолКонОст;
          Стоимость=Запрос.СумКонОст;
        КонецЕсли;
        КолСпис=КолСпис-Списывать;
        Регистр.ОстаткиТоваров.Склад = СкладО;
// по одному складу
        Регистр.ОстаткиТоваров.Товар
= Товар;
        Регистр.ОстаткиТоваров.Сорт = Сорт;
        Регистр.ОстаткиТоваров.Партия = ПартияСписания;
        Регистр.ОстаткиТоваров.Количество = Списывать;
        Регистр.ОстаткиТоваров.СуммаП = Стоимость;
        Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*Списывать,2,1);
        Регистр.ОстаткиТоваров.ФлагДвижения = 2;
// у нас движение внутреннее
        Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
        Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
        Регистр.ОстаткиТоваров.Склад = СкладП;
// по другому складу
        Регистр.ОстаткиТоваров.Товар
= Товар;
        Регистр.ОстаткиТоваров.Сорт = Сорт;
        Регистр.ОстаткиТоваров.Партия = ПартияСписания;
        Регистр.ОстаткиТоваров.Количество = Списывать;
        Регистр.ОстаткиТоваров.СуммаП = Стоимость;
        Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*Списывать,2,1);
        Регистр.ОстаткиТоваров.ФлагДвижения = 2;
        Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
        Регистр.ОстаткиТоваров.ДвижениеПриходВыполнить();
        Регистр.ОборотыТоваров.Склад = СкладО;
        Регистр.ОборотыТоваров.Товар = Товар;
        Регистр.ОборотыТоваров.Сорт = Сорт;
        Регистр.ОборотыТоваров.Количество = Списывать;
        Регистр.ОборотыТоваров.СуммаУ = Стоимость;
        Регистр.ОборотыТоваров.ФлагДвижения = 2;
        Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
        Регистр.ОборотыТоваров.ДвижениеВыполнить();
        Регистр.ОборотыТоваров.Склад = СкладП;
        Регистр.ОборотыТоваров.Товар = Товар;
        Регистр.ОборотыТоваров.Сорт = Сорт;
        Регистр.ОборотыТоваров.Количество = Списывать;
        Регистр.ОборотыТоваров.СуммаУ = Стоимость;
        Регистр.ОборотыТоваров.ФлагДвижения = 2;
        Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
        Регистр.ОборотыТоваров.ДвижениеВыполнить();
      КонецЦикла;
    КонецЦикла;
  ИначеЕсли Константа.МетодСписания=Перечисление.МетодСписания.ЛИФО
Тогда
// Здесь будет записана методика списания
по LIFO
    ТабЗн1=СоздатьОбъект("ТаблицаЗначений");
    ТабЗн2=СоздатьОбъект("ТаблицаЗначений");
    ТабЗн2.НоваяКолонка("Партия","Документ.ПриходнаяНакладная");
    ТабЗн2.НоваяКолонка("КоличествоП","Число",14,2);
    ТабЗн2.НоваяКолонка("СуммаП","Число",19,2);
    ВыбратьСтроки();
    Пока ПолучитьСтроку() = 1 Цикл
      КолВыб=КолО;
      РегОст.УстановитьФильтр(СкладО,Товар,Сорт);
      РегОст.ВыгрузитьИтоги(ТабЗн1,1,1);
      ТабЗн1.Свернуть("4","5,6");
      ТабЗн1.ВыбратьСтроки();
      Пока ТабЗн1.ПолучитьСтроку()=1 Цикл
        Прт=ТабЗн1.Партия;
        Ост=ТабЗн1.Количество;
        Сум=ТабЗн1.СуммаП;
        Если Ост>0 Тогда // есть что проверять
          ТабЗн2.НоваяСтрока();
          ТабЗн2.Партия=Прт;
          ТабЗн2.КоличествоП=Ост;
          ТабЗн2.СуммаП=Сум;
        КонецЕсли;
      КонецЦикла;
      ТабЗн1.Очистить();
      ТабЗн2.Сортировать("1-",1);
// Способ сортировки по убывающей (-)
      ТабЗн2.ВыбратьСтроки();
      Пока ТабЗн2.ПолучитьСтроку()=1 Цикл
        Ост=ТабЗн2.КоличествоП;
        Сум=ТабЗн2.СуммаП;
        ЦенаПП=Окр(Сум/Ост,2,1);
        Парт=ТабЗн2.Партия;
        Если КолВыб>Ост Тогда // Ост
          Регистр.ОстаткиТоваров.Склад = СкладО;
          Регистр.ОстаткиТоваров.Товар = Товар;
          Регистр.ОстаткиТоваров.Сорт = Сорт;
          Регистр.ОстаткиТоваров.Партия = Парт;
          Регистр.ОстаткиТоваров.Количество
= Ост;
          Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенаПП*Ост,2,1);
          Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*Ост,2,1);
          Регистр.ОстаткиТоваров.ФлагДвижения
= 2;
          Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
          Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
          Регистр.ОстаткиТоваров.Склад = СкладП;
          Регистр.ОстаткиТоваров.Товар = Товар;
          Регистр.ОстаткиТоваров.Сорт = Сорт;
          Регистр.ОстаткиТоваров.Партия = Парт;
          Регистр.ОстаткиТоваров.Количество
= Ост;
          Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенаПП*Ост,2,1);
          Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*Ост,2,1);
          Регистр.ОстаткиТоваров.ФлагДвижения
= 2;
          Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
          Регистр.ОстаткиТоваров.ДвижениеПриходВыполнить();
          Регистр.ОборотыТоваров.Склад = СкладО;
          Регистр.ОборотыТоваров.Товар = Товар;
          Регистр.ОборотыТоваров.Сорт = Сорт;
          Регистр.ОборотыТоваров.Количество
= Ост;
          Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенаПП*Ост,2,1);
          Регистр.ОборотыТоваров.ФлагДвижения
= 2;
          Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
          Регистр.ОборотыТоваров.ДвижениеВыполнить();
          Регистр.ОборотыТоваров.Склад = СкладП;
          Регистр.ОборотыТоваров.Товар = Товар;
          Регистр.ОборотыТоваров.Сорт = Сорт;
          Регистр.ОборотыТоваров.Количество
= Ост;
          Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенаПП*Ост,2,1);
          Регистр.ОборотыТоваров.ФлагДвижения
= 2;
          Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
          Регистр.ОборотыТоваров.ДвижениеВыполнить();
          КолВыб=КолВыб-Ост;
        Иначе
          Если КолВыб>0 Тогда // КолВыб
            Регистр.ОстаткиТоваров.Склад
= СкладО;
            Регистр.ОстаткиТоваров.Товар
= Товар;
            Регистр.ОстаткиТоваров.Сорт
= Сорт;
            Регистр.ОстаткиТоваров.Партия
= Парт;
            Регистр.ОстаткиТоваров.Количество
= КолВыб;
            Регистр.ОстаткиТоваров.СуммаП
= Окр(ЦенаПП*КолВыб,2,1);
            Регистр.ОстаткиТоваров.СуммаД
= Окр(Цена*КолВыб,2,1);
            Регистр.ОстаткиТоваров.ФлагДвижения
= 2;
            Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
            Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
            Регистр.ОстаткиТоваров.Склад
= СкладП;
            Регистр.ОстаткиТоваров.Товар
= Товар;
            Регистр.ОстаткиТоваров.Сорт
= Сорт;
            Регистр.ОстаткиТоваров.Партия
= Парт;
            Регистр.ОстаткиТоваров.Количество
= КолВыб;
            Регистр.ОстаткиТоваров.СуммаП
= Окр(ЦенаПП*КолВыб,2,1);
            Регистр.ОстаткиТоваров.СуммаД
= Окр(Цена*КолВыб,2,1);
            Регистр.ОстаткиТоваров.ФлагДвижения
= 2;
            Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
            Регистр.ОстаткиТоваров.ДвижениеПриходВыполнить();
            Регистр.ОборотыТоваров.Склад
= СкладО;
            Регистр.ОборотыТоваров.Товар
= Товар;
            Регистр.ОборотыТоваров.Сорт
= Сорт;
            Регистр.ОборотыТоваров.Количество
= КолВыб;
            Регистр.ОборотыТоваров.СуммаУ
= Окр(ЦенаПП*КолВыб,2,1);
            Регистр.ОборотыТоваров.ФлагДвижения
= 2;
            Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
            Регистр.ОборотыТоваров.ДвижениеВыполнить();
            Регистр.ОборотыТоваров.Склад
= СкладП;
            Регистр.ОборотыТоваров.Товар
= Товар;
            Регистр.ОборотыТоваров.Сорт
= Сорт;
            Регистр.ОборотыТоваров.Количество
= КолВыб;
            Регистр.ОборотыТоваров.СуммаУ
= Окр(ЦенаПП*КолВыб,2,1);
            Регистр.ОборотыТоваров.ФлагДвижения
= 2;
            Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
            Регистр.ОборотыТоваров.ДвижениеВыполнить();
            КолВыб=КолВыб-Ост;
          КонецЕсли;
        КонецЕсли;
      КонецЦикла;
      ТабЗн2.УдалитьСтроки();
    КонецЦикла;
  ИначеЕсли
    Константа.МетодСписания=Перечисление.МетодСписания.По_среднему
Тогда
// Здесь будет записана методика списания
по-среднему
    ВыбратьСтроки();
    Пока ПолучитьСтроку() = 1 Цикл
      КолОст=РегОст.СводныйОстаток(СкладО,Товар,Сорт,,"Количество");
      СумОст=РегОст.СводныйОстаток(СкладО,Товар,Сорт,,"СуммаП");
      ЦенОст=Окр(СумОст/КолОст,2,1);
      Парт=ПолучитьПустоеЗначение("Документ.ПриходнаяНакладная");
      Регистр.ОстаткиТоваров.Склад = СкладО;
      Регистр.ОстаткиТоваров.Товар = Товар;
      Регистр.ОстаткиТоваров.Сорт = Сорт;
      Регистр.ОстаткиТоваров.Партия = Парт;
      Регистр.ОстаткиТоваров.Количество = КолО;
      Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенОст*КолО,2,1);
      Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*КолО,2,1);
      Регистр.ОстаткиТоваров.ФлагДвижения = 2;
      Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
      Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
      Регистр.ОстаткиТоваров.Склад = СкладП;
      Регистр.ОстаткиТоваров.Товар = Товар;
      Регистр.ОстаткиТоваров.Сорт = Сорт;
      Регистр.ОстаткиТоваров.Партия = Парт;
      Регистр.ОстаткиТоваров.Количество = КолО;
      Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенОст*КолО,2,1);
      Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*КолО,2,1);
      Регистр.ОстаткиТоваров.ФлагДвижения = 2;
      Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
      Регистр.ОстаткиТоваров.ДвижениеПриходВыполнить();
      Регистр.ОборотыТоваров.Склад = СкладО;
      Регистр.ОборотыТоваров.Товар = Товар;
      Регистр.ОборотыТоваров.Сорт = Сорт;
      Регистр.ОборотыТоваров.Количество = КолО;
      Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенОст*КолО,2,1);
      Регистр.ОборотыТоваров.ФлагДвижения = 2;
      Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
      Регистр.ОборотыТоваров.ДвижениеВыполнить();
      Регистр.ОборотыТоваров.Склад = СкладП;
      Регистр.ОборотыТоваров.Товар = Товар;
      Регистр.ОборотыТоваров.Сорт = Сорт;
      Регистр.ОборотыТоваров.Количество = КолО;
      Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенОст*КолО,2,1);
      Регистр.ОборотыТоваров.ФлагДвижения = 2;
      Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
      Регистр.ОборотыТоваров.ДвижениеВыполнить();
    КонецЦикла;
  КонецЕсли;
КонецПроцедуры
Здесь мы переставили алгоритмы списания местами,
в расходной накладной при списании по методу FIFO мы использовали
алгоритм выгрузки регистра, а LIFO – запрос, то теперь наоборот,
с соответствующими изменениями.