Мы сталкиваемся с достаточно распространенной, но при этом нетривиальной задачей в 1С:Управление торговлей 11 (УТ 11) – как корректно сопоставить документ РасходныйОрдерНаТовары с конкретными строками документа ЗаказКлиента, особенно когда речь идет о ценах, скидках и частичных отгрузках. Давайте вместе разберем эту проблему и найдем оптимальные пути решения.
Прежде чем предлагать решения, нам необходимо понять, почему эта задача не имеет простого типового ответа. Мы проанализируем архитектуру документов в УТ 11.
1. Различие в назначении документов.
* Документ ЗаказКлиента является, по сути, нашим финансовым документом, фиксирующим намерения клиента, условия сделки, цены, скидки, этапы оплаты и прочие коммерческие условия. Он содержит полную информацию о стоимости каждой позиции.
* Документ РасходныйОрдерНаТовары, напротив, относится к складскому учету. Его основная задача — зафиксировать факт физического перемещения товаров со склада. Он не содержит информации о ценах, скидках, организациях и других финансовых аспектах. Ордер оперирует только количеством и номенклатурой.
2. Сложности с ценами и скидками.
* Представим ситуацию: в одном ЗаказеКлиента одна и та же Номенклатура может быть указана несколькими строками, но с разными ценами. Например, «Молоко» по 300 руб. (1 шт.) и «Молоко» по 250 руб. (1 шт.) – возможно, из-за разных скидок или условий.
* Если РасходныйОрдерНаТовары отгружает только 1 штуку «Молока», то возникает вопрос: какую цену из ЗаказаКлиента мы должны сопоставить? 300 руб. или 250 руб.? Номенклатура в ордере к номеру строки заказа клиента никак не привязана.
* Дополнительную сложность вносят автоматические и ручные скидки, которые могут быть применены к ЗаказуКлиента, изменяя итоговую цену позиций.
3. Частичные отгрузки и пересорты.
* Жизненные ситуации бывают разные: мы можем отгрузить меньше, чем было заказано, или произошел пересорт. Ордер фиксирует то, что фактически уехало со склада, а не то, что было запланировано в заказе.
Таким образом, прямого, автоматического сопоставления РасходногоОрдераНаТовары с конкретными строками ЗаказаКлиента с учетом всех ценовых нюансов в УТ 11 по умолчанию не предусмотрено. Мы должны будем разработать собственный механизм.
Один из наиболее надежных способов получить финансовую информацию, связанную с отгрузкой по ордеру, — это использовать типовой механизм формирования документа РеализацияТоваровИУслуг (РТиУ). Документ РТиУ является мостом между складским ордером и финансовыми проводками, поскольку именно в нем консолидируются данные о ценах, скидках и организации.
Мы рассмотрим подробнее, как это работает:
1. Цепочка документов.
* Основной документ, фиксирующий намерения, — это ЗаказКлиента.
* На его основании создается РасходныйОрдерНаТовары, который отражает фактическую отгрузку со склада.
* На основании РасходногоОрдераНаТовары (или напрямую из ЗаказаКлиента при беспордерной схеме) формируется РеализацияТоваровИУслуг. Именно в РТиУ собираются все данные о ценах, скидках и организации.
2. Идея с программным формированием РТиУ.
* Если нам требуется получить финансовую стоимость товаров из ордера, но без фактического проведения реализации, мы можем программно сформировать документ РеализацияТоваровИУслуг на основании нашего РасходногоОрдераНаТовары.
* После заполнения табличной части Товары в РТиУ, система автоматически рассчитает цены и применит скидки, используя данные из связанного ЗаказаКлиента и настроек ценообразования.
* Получив необходимые данные (цены, суммы), мы можем отменить проведение этого программно созданного РТиУ или даже удалить его, если он нужен был только для получения информации.
3. Изучение типовых алгоритмов.
* В документе РеализацияТоваровИУслуг существует полезная функция «Заполнить/Подобрать товары по заказам/ордерам». Мы настоятельно рекомендуем изучить алгоритмы, используемые в этой функции. Они показывают, как система связывает отгруженные товары с заказами и переносит их в документ. Это поможет нам понять логику и воспроизвести ее программно.
Посмотрим на пример концептуального кода, который показывает, как мы могли бы создать временный РТиУ и получить из него данные:
// Предположим, у нас есть ссылка на РасходныйОрдерНаТовары
Ордер = Документы.РасходныйОрдерНаТовары.НайтиПоНомеру("000000001");
Если Ордер.Пустая() Тогда
Возврат;
КонецЕсли;
// Создаем новый документ РеализацияТоваровИУслуг
НоваяРеализация = Документы.РеализацияТоваровИУслуг.СоздатьДокумент();
НоваяРеализация.Дата = Ордер.Дата;
НоваяРеализация.Склад = Ордер.Склад;
НоваяРеализация.Основание = Ордер.Основание; // Это будет ЗаказКлиента
НоваяРеализация.ДокументОснование = Ордер; // Указываем ордер как основание
// Заполняем табличную часть Товары из ордера
// Здесь может потребоваться вызов типовой функции заполнения,
// или ручное перенесение позиций из табличной части Ордера
// с последующим расчетом цен и скидок.
// В типовых конфигурациях обычно есть общие модули или методы форм,
// которые выполняют эту логику.
// Например, можем использовать метод ЗаполнитьПоОснованию(),
// если он доступен и реализует нужную логику.
// Пример: если метод ЗаполнитьПоОснованию() существует и подходит
// ОбщийМодуль.ЗаполнениеДокументов.ЗаполнитьТабличнуюЧастьПоОснованию(НоваяРеализация, "Товары", Ордер, "Товары");
// Или более детально, перебирая строки ордера:
Для Каждого СтрокаОрдера Из Ордер.Товары Цикл
НоваяСтрока = НоваяРеализация.Товары.Добавить();
НоваяСтрока.Номенклатура = СтрокаОрдера.Номенклатура;
НоваяСтрока.Характеристика = СтрокаОрдера.Характеристика;
НоваяСтрока.Количество = СтрокаОрдера.Количество;
НоваяСтрока.ЕдиницаИзмерения = СтрокаОрдера.ЕдиницаИзмерения;
// ... другие поля, если есть
КонецЦикла;
// После заполнения табличной части, нам нужно "рассчитать" цены и скидки.
// В типовых документах это часто происходит при интерактивном вводе или
// вызове специфических серверных процедур.
// Например:
// ВыполнитьРасчетЦенИСкидок(НоваяРеализация); // Это гипотетическая функция
// Теперь, когда цены и суммы рассчитаны в НовойРеализации.Товары,
// мы можем получить нужную информацию:
Для Каждого СтрокаРеализации Из НоваяРеализация.Товары Цикл
Сообщить("Номенклатура: " + СтрокаРеализации.Номенклатура
+ ", Количество: " + СтрокаРеализации.Количество
+ ", Цена: " + СтрокаРеализации.Цена
+ ", Сумма: " + СтрокаРеализации.Сумма);
КонецЦикла;
// Если документ не нужен, мы можем его пометить на удаление или удалить:
// НоваяРеализация.УстановитьПометкуУдаления(Истина);
// Или: НоваяРеализация.Удалить();
В этом подходе важно понимать, что типовые механизмы расчета цен и скидок часто завязаны на контекст формы или требуют вызова определенных серверных процедур. Возможно, потребуется изучить код обработчиков событий или общих модулей, которые отвечают за заполнение и пересчет табличных частей в РТиУ.
Если нам не требуется точное финансовое сопоставление с ценами из ЗаказаКлиента, а нужна лишь ориентировочная или внутренняя оценка стоимости отгруженных товаров, мы можем привязаться к неким "удельным" значениям.
Мы рассмотрим два основных варианта:
1. Использование закупочной/отпускной цены или себестоимости товара (ССТ).
* Мы можем принять решение, что для целей сопоставления РасходногоОрдераНаТовары с ЗаказомКлиента (например, для расчета стоимости доставки или внутренней аналитики) будем использовать фиксированную закупочную цену, текущую отпускную цену или рассчитанную себестоимость товара.
* Эти данные можно получить из соответствующих регистров или справочников.
* Расчет себестоимости товаров в УТ 11 — это сложный процесс, который осуществляется путем решения линейных уравнений. Пользователь может выбрать способ формирования себестоимости: СредняяЗаМесяц или ФИФО.
* Нам нужно будет учитывать, что дополнительные расходы могут быть распределены на себестоимость товаров пропорционально количеству, себестоимости, весу или объему номенклатуры. Однако, существуют сложности с распределением дополнительных расходов, возникающих при отгрузке товара клиенту, так как эти расходы могут появляться после перехода права собственности и не всегда логично ложатся на себестоимость товара.
2. Распределение сумм по пропорции.
* Если у нас есть общая сумма по ЗаказуКлиента и общее количество отгруженной номенклатуры в РасходномОрдереНаТовары, мы можем попытаться распределить общую стоимость заказа пропорционально количеству отгруженных товаров.
* Этот метод может быть достаточно сложным, особенно если в заказе несколько распоряжений и несколько ордеров. Он также не учитывает нюансы разных цен на одну и ту же номенклатуру, но может дать приблизительную оценку.
* Мы говорим о пропорции, когда используем любые вычисления через некие удельные значения с числителем и знаменателем. Например, если общая сумма заказа 1000 руб. за 10 шт. товара, а ордер отгружает 5 шт., то пропорциональная сумма составит 500 руб.
Посмотрим на пример концептуального кода для расчета на основе себестоимости:
// Предположим, у нас есть ссылка на РасходныйОрдерНаТовары
Ордер = Документы.РасходныйОрдерНаТовары.НайтиПоНомеру("000000002");
Если Ордер.Пустая() Тогда
Возврат;
КонецЕсли;
Для Каждого СтрокаОрдера Из Ордер.Товары Цикл
// Получаем себестоимость для Номенклатуры и Характеристики на дату ордера
// Это может быть запрос к регистру накопления "СебестоимостьТоваров"
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПартииТоваровНаСкладахОстатки.Себестоимость КАК Себестоимость
|ИЗ
| РегистрНакопления.ПартииТоваровНаСкладах.Остатки(
| &Дата,
| Номенклатура = &Номенклатура
| И Характеристика = &Характеристика
| И Склад = &Склад) КАК ПартииТоваровНаСкладахОстатки";
Запрос.УстановитьПараметр("Дата", Ордер.Дата);
Запрос.УстановитьПараметр("Номенклатура", СтрокаОрдера.Номенклатура);
Запрос.УстановитьПараметр("Характеристика", СтрокаОрдера.Характеристика);
Запрос.УстановитьПараметр("Склад", Ордер.Склад); // Или другой способ получения себестоимости
РезультатЗапроса = Запрос.Выполнить().Выбрать();
Если РезультатЗапроса.Следующий() Тогда
СебестоимостьЕдиницы = РезультатЗапроса.Себестоимость / СтрокаОрдера.Количество; // Если себестоимость в запросе общая по партии
// Или, если запрос возвращает себестоимость единицы:
// СебестоимостьЕдиницы = РезультатЗапроса.Себестоимость;
СуммаПоСебестоимости = СебестоимостьЕдиницы * СтрокаОрдера.Количество;
Сообщить("Номенклатура: " + СтрокаОрдера.Номенклатура
+ ", Количество: " + СтрокаОрдера.Количество
+ ", Себестоимость за единицу: " + Формат(СебестоимостьЕдиницы, "ЧДЦ=2")
+ ", Общая сумма по себестоимости: " + Формат(СуммаПоСебестоимости, "ЧДЦ=2"));
Иначе
Сообщить("Себестоимость для номенклатуры " + СтрокаОрдера.Номенклатура + " не найдена.");
КонецЕсли;
КонецЦикла;
Метод с условными ценами или себестоимостью упрощает задачу, но может не дать полной картины финансовых взаимоотношений с клиентом, так как не учитывает все нюансы цен и скидок, зафиксированных в ЗаказеКлиента.
Для успешного решения задачи нам потребуется глубокое понимание структуры и связей документов в УТ 11, а также умение работать с программным интерфейсом. Мы перечислим ключевые объекты и подходы, которые помогут нам в этом.
* ДокументОбъект.ЗаказКлиента: Это наш основной документ, содержащий всю информацию о намерениях клиента, включая номенклатуру, характеристики, цены, скидки и условия поставки. Обратите внимание на табличную часть Товары и связанные с ней регистры, которые хранят информацию о ценах и скидках.
* ДокументОбъект.РасходныйОрдерНаТовары: Документ складского учета. Важно, что его табличная часть Товары содержит только номенклатуру и количество.
* ДокументОбъект.РеализацияТоваровИУслуг: Ключевой документ для получения финансовой информации. Именно в нем реализованы механизмы расчета цен и скидок на основе ЗаказаКлиента. Изучите его методы заполнения и обработки.
* РегистрыНакопления:
* ТоварыНаСкладах: Для получения текущих остатков товаров.
* СебестоимостьТоваров: Для получения данных о себестоимости.
* ПартииТоваровНаСкладах: Для более детального анализа себестоимости в разрезе партий.
* ОбщиеМодули: Многие типовые алгоритмы заполнения и расчета документов вынесены в общие модули. Изучите модули, связанные с ценообразованием, скидками и заполнением документов реализации. Например, модули, отвечающие за работу с табличными частями документов.
* ТабличныеЧастиДокументов: Работа с данными в табличных частях Товары документов является ключевой. Мы будем программно добавлять строки, заполнять поля Номенклатура, Количество, а затем инициировать расчет Цены и Суммы.
* Методы работы с формами: Функционал "Заполнить/Подобрать товары по заказам/ордерам" в РеализацииТоваровИУслуг является отличным примером того, как система связывает данные. Если мы хотим воспроизвести эту логику, нам, возможно, придется изучить код этих команд.
* СоглашенияСКлиентами и ВидыЦен: Помните, что цены в ЗаказеКлиента формируются на основе выбранного соглашения, типа цен и действующих скидок. Понимание этих механизмов критически важно.
* ПравилаРасчетаСкидок: В УТ 11 автоматические скидки могут быть настроены по различным правилам (процент за объем, на номенклатуру из списка, специальная цена, подарок). Эти правила влияют на конечную цену в ЗаказеКлиента.
В реальной жизни не всегда все идеально совпадает. Мы должны быть готовы к ситуациям, когда отгруженное количество не соответствует заказанному.
* В случае расхождений между заказанным и фактически отгруженным количеством (недостача или излишек), система предусматривает оформление документа АктОРасхожденияхПослеОтгрузки.
* Для отражения недостачи в финансовом учете используется документ СписаниеНедостачТоваров, а для излишков – ОприходованиеИзлишковТоваров.
* Если по тому же заказу вместо недопоставленного товара необходимо отгрузить новый товар, на основании заказа можно оформить новую реализацию, указав для строки товара признак сверхЗаказа.
Таким образом, решение задачи сопоставления РасходногоОрдераНаТовары с ЗаказомКлиента в УТ 11 требует либо программной доработки с имитацией создания РеализацииТоваровИУслуг для получения финансовых данных, либо использования условных цен/себестоимости для промежуточных расчетов. Важно тщательно проанализировать требования к точности сопоставления и выбрать наиболее подходящий метод.