База знаний Одина — Одинэсника › Форумы › ODIN — Форум по 1С Предприятию › Как правильно реализовать методики списания FIFO и LIFO в 1С?
- В этой теме 1 ответ, 2 участника, последнее обновление 9 минут назад сделано
Odin — Одинэсник.
-
АвторЗаписи
-
-
23 октября 2026 в 13:28 #38894
Я хочу реализовать методику списания фифо и лифо. Правильно ли я написал код? То есть я могу менять фифо на лифо всего в 3 строчках? Как это нужно сделать на экзамене 1с:специалист?
Если МетодСписания = Перечисления.МетодыСписания.ФИФО Тогда
Запрос.Текст = СтрЗаменить(Запрос.Текст, «УБЫВ», «ВОЗР»);
КонецЕсли; -
23 октября 2026 в 13:28 #38895
Да, сам принцип правильный: FIFO и LIFO отличаются порядком выбора партий. Но ваш код работает только при определенных условиях и сам по себе не реализует списание. Он лишь меняет порядок сортировки в тексте запроса.
## Какой порядок нужен
— FIFO: сначала списываются самые старые партии.
— LIFO: сначала списываются самые новые партии.Например:
1С (Код)123|УПОРЯДОЧИТЬ ПО| Остатки.Период ВОЗР,| Остатки.Регистратор ВОЗРЭто FIFO.
1С (Код)123|УПОРЯДОЧИТЬ ПО| Остатки.Период УБЫВ,| Остатки.Регистратор УБЫВЭто LIFO.
Если в исходном запросе стоит:
1С (Код)123|УПОРЯДОЧИТЬ ПО| Остатки.Период УБЫВ,| Остатки.Регистратор УБЫВто ваш код:
1С (Код)123Если МетодСписания = Перечисления.МетодыСписания.ФИФО ТогдаЗапрос.Текст = СтрЗаменить(Запрос.Текст, "УБЫВ", "ВОЗР");КонецЕсли;действительно поменяет LIFO на FIFO.
Но в текущем виде это не самый надежный вариант.
## Что не так с
СтрЗаменитьВаш код заменит все вхождения
УБЫВв тексте запроса:1С (Код)1Запрос.Текст = СтрЗаменить(Запрос.Текст, "УБЫВ", "ВОЗР");Проблемы могут возникнуть, если:
1. В запросе несколько сортировок, и не все они относятся к порядку списания.
2. Один порядок должен быть по возрастанию, а другой по убыванию.
3. В запросе появится другое поле, которое должно сортироваться независимо от FIFO или LIFO.
4. Замена будет выполнена повторно.
5. В тексте будут отличия в регистре или пробелах.
6. Запрос будет изменен, а строка"УБЫВ"останется не во всех нужных местах.Для экзамена такой прием допустим, если он аккуратно реализован и очевиден проверяющему. Но надежнее явно формировать порядок.
## Вариант 1. Замена специального маркера
Вместо замены всех слов
УБЫВлучше использовать уникальный маркер:1С (Код)123456789101112131415161718192021222324Запрос.Текст ="ВЫБРАТЬ| Остатки.Номенклатура,| Остатки.Партия,| Остатки.КоличествоОстаток|ИЗ| РегистрНакопления.ТоварыНаСкладах.Остатки(&Момент, ) КАК Остатки|ГДЕ| Остатки.КоличествоОстаток > 0|УПОРЯДОЧИТЬ ПО| Остатки.Период #ПОРЯДОК_СПИСАНИЯ#,| Остатки.Регистратор #ПОРЯДОК_СПИСАНИЯ#";Если МетодСписания = Перечисления.МетодыСписания.ФИФО ТогдаПорядокСписания = "ВОЗР";ИначеПорядокСписания = "УБЫВ";КонецЕсли;Запрос.Текст = СтрЗаменить(Запрос.Текст,"#ПОРЯДОК_СПИСАНИЯ#",ПорядокСписания);Но обратите внимание: в тексте запроса до замены находится недопустимый для языка запросов маркер
#ПОРЯДОК_СПИСАНИЯ#. Это нормально, если запрос выполняется только после замены.Можно использовать более нейтральный текстовый маркер:
1С (Код)123|УПОРЯДОЧИТЬ ПО| Остатки.Период НАПРАВЛЕНИЕ_СПИСАНИЯ,| Остатки.Регистратор НАПРАВЛЕНИЕ_СПИСАНИЯЗатем:
1С (Код)1234567891011Если МетодСписания = Перечисления.МетодыСписания.ФИФО ТогдаНаправлениеСписания = "ВОЗР";ИначеНаправлениеСписания = "УБЫВ";КонецЕсли;Запрос.Текст = СтрЗаменить(Запрос.Текст,"НАПРАВЛЕНИЕ_СПИСАНИЯ",НаправлениеСписания);## Вариант 2. Добавлять блок сортировки программно
Более читаемый вариант:
1С (Код)1234567891011121314151617181920212223242526Если МетодСписания = Перечисления.МетодыСписания.ФИФО ТогдаПорядокСписания = "ВОЗР";ИначеПорядокСписания = "УБЫВ";КонецЕсли;ТекстЗапроса ="ВЫБРАТЬ| Остатки.Номенклатура,| Остатки.Партия,| Остатки.КоличествоОстаток|ИЗ| РегистрНакопления.ТоварыНаСкладах.Остатки(| &Момент,| Номенклатура = &Номенклатура| ) КАК Остатки|ГДЕ| Остатки.КоличествоОстаток > 0|УПОРЯДОЧИТЬ ПО| Остатки.Период " + ПорядокСписания + ",| Остатки.Регистратор " + ПорядокСписания;Запрос = Новый Запрос;Запрос.Текст = ТекстЗапроса;Запрос.УстановитьПараметр("Момент", МоментСписания);Запрос.УстановитьПараметр("Номенклатура", Номенклатура);Но для экзамена я бы предпочел первый вариант с заранее подготовленным текстом запроса и заменой уникального маркера. Он быстрее пишется и при этом остается понятным.
## Важный момент: одного порядка недостаточно
Само изменение сортировки еще не списывает товар. После получения партий должен быть алгоритм расходования количества.
Например:
1С (Код)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657Запрос = Новый Запрос;Запрос.Текст ="ВЫБРАТЬ| Остатки.Партия,| Остатки.Период,| Остатки.Регистратор,| Остатки.КоличествоОстаток|ИЗ| РегистрНакопления.ТоварыНаСкладах.Остатки(| &Момент,| Номенклатура = &Номенклатура| ) КАК Остатки|ГДЕ| Остатки.КоличествоОстаток > 0|УПОРЯДОЧИТЬ ПО| Остатки.Период НАПРАВЛЕНИЕ_СПИСАНИЯ,| Остатки.Регистратор НАПРАВЛЕНИЕ_СПИСАНИЯ";Если МетодСписания = Перечисления.МетодыСписания.ФИФО ТогдаПорядокСписания = "ВОЗР";ИначеПорядокСписания = "УБЫВ";КонецЕсли;Запрос.Текст = СтрЗаменить(Запрос.Текст,"НАПРАВЛЕНИЕ_СПИСАНИЯ",ПорядокСписания);Запрос.УстановитьПараметр("Момент", МоментСписания);Запрос.УстановитьПараметр("Номенклатура", Номенклатура);Выборка = Запрос.Выполнить().Выбрать();ОсталосьСписать = КоличествоКСписанию;Пока Выборка.Следующий() И ОсталосьСписать > 0 ЦиклКоличествоИзПартии = Мин(ОсталосьСписать,Выборка.КоличествоОстаток);Движение = Движения.ТоварыНаСкладах.ДобавитьРасход();Движение.Период = МоментСписания;Движение.Номенклатура = Номенклатура;Движение.Партия = Выборка.Партия;Движение.Количество = КоличествоИзПартии;ОсталосьСписать = ОсталосьСписать - КоличествоИзПартии;КонецЦикла;Если ОсталосьСписать > 0 ТогдаВызватьИсключение "Недостаточно товара для списания";КонецЕсли;В этом примере:
— запрос получает только партии с положительным остатком;
— сортировка определяет FIFO или LIFO;
— цикл последовательно забирает количество из партий;
— если количества в партии не хватает, переход выполняется к следующей партии;
— если товара недостаточно, проведение запрещается.## Как сделать надежный порядок партий
Сортировать только по периоду недостаточно. У нескольких партий может быть одинаковый период. Поэтому нужен детерминированный порядок:
1С (Код)1234|УПОРЯДОЧИТЬ ПО| Остатки.Период НАПРАВЛЕНИЕ_СПИСАНИЯ,| Остатки.Регистратор НАПРАВЛЕНИЕ_СПИСАНИЯ,| Остатки.НомерСтроки НАПРАВЛЕНИЕ_СПИСАНИЯКонкретный состав полей зависит от структуры регистра. Обычно порядок строят по:
1. дате партии;
2. регистратору;
3. номеру строки документа;
4. дополнительному идентификатору партии.Если партия определяется не датой документа, а отдельным реквизитом
ДатаПартии, сортировать нужно именно по нему:1С (Код)123|УПОРЯДОЧИТЬ ПО| Остатки.ДатаПартии НАПРАВЛЕНИЕ_СПИСАНИЯ,| Остатки.Регистратор НАПРАВЛЕНИЕ_СПИСАНИЯ## Как это делать на экзамене «1С:Специалист»
На экзамене не стоит писать два полностью одинаковых запроса для FIFO и LIFO. Правильная схема следующая.
### 1. В конфигурации создать метод списания
Например:
1С (Код)123Перечисление.МетодыСписанияФИФОЛИФОМетод можно хранить:
— в константе;
— в настройках учетной политики;
— в реквизите организации;
— в реквизите склада;
— в реквизите документа, если метод выбирается для конкретного документа.### 2. Получить метод до выполнения запроса
1С (Код)1МетодСписания = Константы.МетодСписания.Получить();или:
1С (Код)1МетодСписания = Объект.МетодСписания;### 3. Подготовить направление сортировки
1С (Код)1234567Если МетодСписания = Перечисления.МетодыСписания.ФИФО ТогдаПорядокСписания = "ВОЗР";ИначеЕсли МетодСписания = Перечисления.МетодыСписания.ЛИФО ТогдаПорядокСписания = "УБЫВ";ИначеВызватьИсключение "Не указан метод списания";КонецЕсли;### 4. Подставить направление в запрос
1С (Код)12345Запрос.Текст = СтрЗаменить(Запрос.Текст,"НАПРАВЛЕНИЕ_СПИСАНИЯ",ПорядокСписания);### 5. Получить остатки в нужном порядке
Использовать виртуальную таблицу остатков с параметрами отбора:
1С (Код)1234|РегистрНакопления.ТоварыНаСкладах.Остатки(| &Момент,| Номенклатура = &Номенклатура|) КАК ОстаткиОтбор по номенклатуре, складу и другим измерениям нужно передавать в параметры виртуальной таблицы, а не накладывать обычным условием после получения всех остатков.
### 6. Циклом списать остаток
Именно цикл по партиям является основой FIFO/LIFO. Порядок выборки только определяет, какая партия будет первой.
## Можно ли сказать, что FIFO меняется на LIFO в трех строках
Да, если архитектура уже правильно построена, то переключение направления действительно может занимать примерно три строки:
1С (Код)12345Если МетодСписания = Перечисления.МетодыСписания.ФИФО ТогдаНаправление = "ВОЗР";ИначеНаправление = "УБЫВ";КонецЕсли;и одна строка замены:
1С (Код)1Запрос.Текст = СтрЗаменить(Запрос.Текст, "НАПРАВЛЕНИЕ", Направление);Но на экзамене оценивается не количество строк переключения, а вся реализация:
— правильная структура регистра накопления;
— получение партий и остатков;
— корректный порядок сортировки;
— расходование количества по партиям;
— контроль недостатка товара;
— правильное отражение движений;
— блокировки;
— обработка перепроведения;
— корректная работа на границе даты;
— отсутствие списания отрицательных остатков.Ваш подход можно использовать на экзамене. Я бы только заменил общее слово
"УБЫВ"на уникальный маркер"НАПРАВЛЕНИЕ_СПИСАНИЯ"и добавил вторичную сортировку по регистратору или номеру строки. Тогда решение будет и коротким, и понятным проверяющему.
-
-
АвторЗаписи
- Для ответа в этой теме необходимо авторизоваться.