1. В параметрах закрытия склада имеется поле "максимальная пропускная способность”. Именно в этом поле и указывается максимальное число итераций, которое система может выполнить на стадии прогонки себестоимости. Если при выполнении процедуры прогонки себестоимости добрались до итерации, указанной в этом поле, то при выполнении этой итерации, коррекция себестоимости (пришедшая с предыдущей итерации в таблице InventCostListTrans) по данной приходной проводке не переносится на сопоставленный с данным приходом расход, а списывается с прихода на счет прибылей и убытков.
2. Также в параметрах закрытия склада имеется поле "Минимальная коррекция пропускной способности”. Если значение коррекции себестоимости, пришедшая с предыдущей итерации в таблице inventCostListTrans, меньше этого значения, то эта коррекция не переносится связанный с данным приходом расход, а просто списывается с прихода на счет прибылей и убытков. Хочу подчеркнуть, что этот параметр работает для КАЖДОЙ строки таблицы inventCostListTrans. То есть – если у нас в inventCostListTrans имеется три коррекции на 2,10 и 80 копеек, значение параметра "минимальная коррекция пропускной способности” установлена в 5 копеек, то списание в прибыли и убытки будет выполнено только для первой из коррекций. По остальным коррекциям итерации прогонки будут продолжаться.
Подробнее об списании коррекций – в разделе "О списании ошибок округления и корректировок при прогонке себестоимости.”
Имеется любопытная особенность прогонки себестоимости о которой я здесь не написал, но которая часто вызывает недоумение у пользователей. Классический вопрос - "У меня была закрытая проводка, но она каким-то образом оказалась модифицирована при закрытии склада. Почему ?" Ответ на этот вопрос состоит из нескольких шагов:
-
Проводка по складу помечается как закрытая при выполнении двух условий: Должны совпадать количество в проводке и сопоставленное количество; Должны совпадать себестоимость в проводке и сопоставленная себестоимость (то есть costAmountPosted+costAmountAdjustment==costAmountSettled). (если быть честным - требуется не абсолютное равенство, а лишь разница меньше чем некая дельта). Соответственно - если мы по каким-то причинам переоцениваем закрытую проводку (все равно - просто переоценкой лота в соответствующей форме или потому что у нас эта ЗАКРЫТАЯ проводка попала в цикл графа прогона себестоимости), такая проводка немедленно становится открытой.
-
На самом деле - еще до запуска процедуры сопоставления приходов и расходов, система сканирует все открытые и хотя бы частично сопоставленные по количеству приходные проводки, расcчитывает по ним разницу между себестоимостью и сопоставленной себестоимостью и отправляет найденную разницу во все тот же граф прогона себестоимости. (занимается этим, кстати, метод inventCostItemDim.updateReceiptAdjustment(), который вызывается ДО метода inventCostItemDim.updateModel(), который занимается собственно сопоставлением приходов и расходов.
Я когда-то задумывался, а нельзя ли было решить эту проблему по другому ? Например - при попытке корректировать закрытую проводку, вместо всяких прогонок себестоимости автоматически списывать сумму коррекции на счет прибылей и убытков. Ну то есть - откорректировали себестоимость проводкой Д 10 К 25.транзит и тут же списали ее проводкой Д 91. округления К 10. Однако у этого подхода есть один очень существенный минус. Если наша приходная проводка закрыта, это совсем не означает что товар уже совсем окончательно и безповоротно продан или списан за пределы хозяйствующего субъекта. Его запросто могли просто переместить на соседний склад. Тогда у нас есть закрытые друг на друга проводки закупки и списания по переносу и вполне себе открытая проводка прихода на соседний склад. Теперь - если мы доначисляем накладные расходы на транспортировку и растаможку (а они иногда могут быть сопоставимы с закупочной стоимостью), они у нас, при подобном подходе, не попадут на себестоимость окончательного списания за пределы организации (то есть продажи скорее всего), а автоматически попадут на счета прибылей и убытков в том периоде в котором мы закупили. В итоге - маржа по продаже, которая у нас когда-то все-таки случится, будет неправдоподобно высокой, поскольку в затраты по продаже не попали заготовительные расходы. Так что - похоже что альтернативы предложенному подходу просто не существует.
Ну и в завершение темы, следует сказать, что одной из дополнительных составляющих прогона себестоимости в версии 2009, стала коррекция и перерасчет непрямых затрат по производственным заказам. Об этих непрямых затратах и их вычислении я напишу ниже, в секции "Структура себестоимости и непрямые затраты".
Разноска в ГК
Прежде всего, хочу отметить, что разноска в ГК выполняется только в том случае, если в параметрах закрытия склада была установлена галка "Обновить главную книгу». Смысла не устанавливать эту галку я не вижу, поскольку начиная еще с версии Axapta 2.5Sp1Hf1, разноска стала выполняться достаточно быстро по сравнению со всеми остальными этапами закрытия склада и отключение этой галки не приводит к серьезному повышению быстродействия этой процедуры.
На предыдущих этапах закрытия склада была заполнена таблица складских сопоставлений (InventSettlement) в которой помимо собственно сопоставленных количеств, сопоставленных сумм и сумм коррекций находится также информация, необходимая для создания бухгалтерских проводок по выполненной коррекции – счет, коррсчет, аналитика, разноска для счета и коррсчета. Поэтому процедура разноски закрытия склада работает достаточно просто. Она группирует суммы коррекции в разрезе этих бухгалтерских параметров, а потом делает соответствующие проводки в ГК. Поэтому – нет особой необходимости в процедуре, которая бы позволяла выверять проводки в ГК по закрытию склада со складскими проводками. Вся информация по счетам аналитикам и тп находится в таблице складских сопоставлений. Если у вас при закрытии склада сгенерировались проводки в ГК с какими-то неожиданными аналитиками или счетами – ищите эти счета и аналитики в таблице сопоставлений. Ну а из этой таблицы уже можно перейти к исходным складским проводкам и попытаться понять – на основании каких операций были сгенерированы эти странные проводки.
Кроме того – на разноску влияет параметр процедуры закрытия склада, называющийся спецификация. В оригинальной (нелокализованной) версии DAX, этот параметр позволял процедуре разноски группировать проводки не только по бухгалтерским параметрам, но и по коду номенклатуры, по которой была выполнена коррекция или коду ее номенклатурной группы. То есть – даже если операции с разными номенклатурами породили коррекции с одинаковыми аналитиками, счетами и корсчетами, в ГК эти коррекции попадали двумя отдельными проводками. К сожалению – этот режим оказался несовместимым с механизмом корреспонденции счетов, используемым в российской версии DAX. Поэтому – если режим корреспонденции счетов включен, то группировка проводок по номенклатуре или номенклатурным группам невозможна. У меня этот факт не смущает, поскольку, как я уже сказал, выверять проводки в ГК по процедуре закрытия гораздо удобнее и легче с помощью таблицы складских сопоставлений (inventSettlement).
Любопытный момент: Как система догадывается что для корректировок тех складских проводок, которые не порождали разносок в главную книгу (например - складских проводок переноса) не надо делать проводок в главную книгу и в момент закрытия склада ? В момент разноски исходной складской проводки, система записывает в связанную со складской проводкой таблицу InventTransPosting информацию о счете и коррсчете разноски, использовавшейся аналитике и, самое главное, о том была ли вообще какая-то разноска в главную книгу (поле isPosted), или счета и аналитика были заполнены исключительно для общности. Далее - при создании сопоставлений и коррекций складской проводки при закрытии склада, система использует для заполнения счета, коррсчета и финансовой аналитики данные из inventTransPosting. При этом, если по исходной складской проводке не было создано проводок ГК (isPosted==NoYes::No), то в складском сопоставлении (inventSettlement) поля счетов и разносок не будут заполнены и класс, разносящий складские сопоставления эти строки таблицы просто проигнорирует.
Кроме того, в версии 2009 кроме разноски коррекций в главную книгу, система на заключительном этапе рассчитывает и списывает отклонения между стандартной и фактической себестоимостью (для новой модели стандартной себестоимости), возникшие в результате прогонки коррекций. Подробнее об этом написано в разделе "Новая стандартная себестоимость"
О параллельном закрытии склада с нескольких рабочих мест.
Наиболее значительным изменением в процедуре закрытия склада со времен выхода первой локализованной версии 2.1 в 2000ом году, стала реализация параллельного закрытия склада с нескольких рабочих станций впервые выпущенная в составе международного Service Pack 2 для Axapta 3.0. На мой взгляд - если до выхода этого пакета обновления низкая производительность процедуры закрытия склада иногда становилась неразрешимой проблемой, то с его выходом – большая часть проблем производительности была снята.
Итак – рассмотрим процедуру закрытия склада в многопользовательском режиме поподробнее:
Того клиента DAX, на котором была первоначально запущена процедура закрытия склада мы в дальнейшем будем называть мастер-клиентом. Всех остальных клиентов – клиентами – помощниками. Напомню, что запуск клиента-помошника выполняется нажатием кнопки Рассчет->Помошь в расчете. При этом в списке закрытий склада должно быть выбрано незаконченное закрытие склада.
В момент запуска процедуры закрытия склада на мастер-клиенте, он записывает параметры закрытия склада в таблицу “Закрытие запасов” (InventClosing) для того, чтобы эту информацию могли бы потом использовать клиенты-помощники. После этого мастер-клиент пишет в таблицу “Список рассчета”(inventCostList) коды той номенклатуры, по которой имеются незакрытые операции. Далее – и мастер-клиент и клиенты-помошники начинают сопоставлять открытые складские проводки по каждой из номенклатур, попавших в эту таблицу. Данный процесс считается нулевой итерацией закрытия склада. Как я уже написал в разделе "Прогон себестоимости”, во время сопоставления, система порождает записи в таблице InventCostListTrans, которые в дальнейшем будут использоваться для итераций прогона себестоимости. Надо сказать, что если в таблицу inventCostListTrans попала хотя бы одна запись для некоторой номенклатуре, то запись об этой номенклатуре попадает также и в таблицу InventCostList. Это необходимо для координации совместной работы нескольких клиентов на стадии прогона себестоимости.
На стадии прогона себестоимости, система действует по похожему алгоритму. Каждый клиент бежит по таблице InventCostList и по каждой из попавших в эту таблицу номенклатур обрабатывает коррекции себестоимости (прогоняет их по графу сопоставлений), попавшие в таблицу inventCostListTrans на прошлой итерации закрытия склада.
Разноска закрытия склада в ГК выполняется только с мастер-клиента.
Если во время выполнения закрытия склада нажать кнопку Рассчет->Останов расчета, то закрытие склада будет приостановлено. После этого можно будет повторно нажать кнопку Рассчет->Помощь в закрытии склада и закрытие склада будет продолжена. В этом случае – мастер-клиентом станет тот клиент, который первый присоединится к незавершенной процедуре закрытия склада.
Если вы используете при параллельном закрытии склада больше 2-3 клиентов, то стоит контролировать загрузку сервера БД и AOS. После того как одна из них добралась процентов до 60-70, подключать к закрытию новых клиентов уже не имеет смысла. Кроме того, опыт показывает, что хотя классы закрытия склада выполняются на клиенте, с одной рабочей станции можно запустить 2 или даже 3 клиента, поскольку часть времени они не создают нагрузку на процессор, поскольку ждут завершения операции на AOS или БД. Хочу также заметить, что на стадии сопоставления система создает значительно бОльшую нагрузку на сервер БД чем на стадии прогонки себестоимости. Поэтому – до момента начала прогонки себестоимости не стоит подключать к процедуре закрытия склада слишком большое количество клиентов.
Хотя авторы системы многопользовательского закрытия склада предназначали таблицы inventCostList и inventCostListTrans исключительно как некий внутрисистемный инструмент для взаимодействия между несколькими клиентами, в качестве побочного эффекта – эти таблицы являются прекрасным инструментом для мониторинга процесса закрытия склада. Поэтому прежде чем приступить к обсуждению того, как этот процесс мониторить – давайте посмотрим структуру данных таблиц:
InventCostList
|
Поле |
Описание |
|
ItemId |
Код номенклатуры по которой требуется выполнять закрытие |
|
Voucher |
Номер документа ГК – используется для связи с таблицей закрытия (inventClosing) |
|
CostNum,NumOfIteration |
Поля с обратными по отношению к друг другу значениями: NumOfIteration – номер текущей итерации прогонки себестоимости; CostNum – обратное значение. Грубо говоря – максимальное число итераций минус номер текущей итерации. |
InventCostListTrans
|
Поле |
Описание |
|
ItemId |
Код номенклатуры по которой требуется прогонка себестоимости |
|
InventTransId |
Номер приходного лота, на который требуется перенести коррекцию на очередной итерации прогонки себестоимости |
|
InventTransIdReturn |
Номер возвращаемого лота. Используется в тех случаях,если при возврате заказа (точнее – вообще складского списания) был указан номер возвращаемого лота (то есть – исходного лота по которому было выполнено списание). Для повышения производительности закрытия склада этот случай обрабатывается специальным образом: Вместо того чтобы брать сумму коррекции на данной итерации из поля adjustment, система просто рассчитывает себестоимость исходной проводки списания и приравнивает к ней себестоимость возврата |
|
VoucherPhysical |
Используется только для возвратов и карантинного заказа. Нужен для корректной связи с исходной проводкой, из которой был порожден данный возврат или карантинный заказ. |
|
Voucher |
Номер документа ГК – используется для связи с таблицей закрытия (inventClosing) |
|
NumOfIteration |
Номер итерации прогонки себестоимости. Нужен для того чтобы координировать действия клиентов и какой-нибудь клиент не начал обрабатывать итерацию N+1, пока все остальные трудятся еще над итерацией N |
|
Adjustment |
Собственно – сумма коррекции, которую нужно провести на по данной складской проводке на данной итерации. |
Считается, что стадия сопоставления приходов и расходов соответствует номеру итерации ноль. На этой итерации в таблице inventCostListTrans записей нет.
В версии 2009 подход к технической организации многопользовательского закрытия склада. Прежде всего - это связано с переходом на использование технологии нового пакетного сервера. Хотя тема эта интересная и сама по себе заслуживает отдельной статьи, я все-таки кратко рассмотрю основные идеи, стоящие за новой технологией пакетного сервера.
-
В версии 2009 пакетные задания исполняются не на выделенном компьютере (компьютерах) а на сервере приложений. Сделано это не из стремления сэкономить клиенту 800 долларов на выделенном пакетном сервере, а для того чтобы предоставить среду распараллеливания трудоемких вычислений. Понятно что число ядер в процессоре будет увеличиваться быстро, а производительность каждого ядра будет расти в лучшем случае на десятки процентов на каждое удвоение числа ядер. Поэтому если мы хотим обеспечить задел по производительности, необходимо подумать о возможности распараллеливать трудоемкие алгоритмы Dynamics AX на несколько нитей. Гораздо логичнее реализовать этот механизм на базе сервера приложений (который и так уже и многопользовательский и многопоточный), чем на базе старого пакетного сервера, выполняющегося на обычном клиенте DAX. Старый клиент и старый пакетный сервера, в принципе, остались, но понятно что они потихоньку отживут.
-
Новая пакетная инфраструктура поддерживает программный API для постановки заданий в очередь. (Класс BatchHeader). Можно указывать зависимости между заданиями или создавать несколько однотипных заданий исполняемых в паралель.
-
Новый API поддержан для некоторых особо вычислительно сложных задач. На мой взгляд - нормальная поддержка сделана для закрытия склада и сводного планирования, более или менее приличная - для разноски журналов главной книги и, в общем, достаточно рудиментарная - для разноски документов по заказу и закупке (насколько я понял - там она играет только в случае, когда мы разносим много накладных по множеству заказов/закупок. Время разноски ОДНОЙ накладной по ОДНОЙ многострочной закупке или заказу этот механизм не уменьшит. Впрочем - заказы и закупки на несколько тысяч строк встречаются довольно нечасто, так что возможно я просто придираюсь.)
В нашем конкретном случае, для того чтобы распараллелить закрытие склада в версии 2009, нам достаточно в параметрах модуля управления запасами указать группу пакетных заданий для запуска помощников (Helpers Batch Group) и число помощников (Extra Batch Helpers). Рекомендации по настройке числа помощников мне дать трудно,(все таки я на практике этот механизм не применял), но я бы начал эксперименты с числа ядер на сервере приложений, помноженного на два. Естественно - при этом в настройке пакетного сервера в форме администрирования серверов (Administration->Setup->Server Configuration->Batch Server Schedule) надо установить число нитей, не меньшее чем число помощников. (Конечно если у вас сервер в это время загружен обычной пользовательской нагрузкой - можно поставить число нитей и поменьше. Просто реальное число активных помощников будет равняться минимуму из значения в параметрах управления запасами и числом нитей для данного временного интервала в форме администрирования серверов).
Старый пользовательский интерфейс для останова/возобновления процедуры закрытия остался на месте, просто он теперь останавливает процессы-помощники на пакетном сервере, а не на обычных рабочих местах как в старой версии.
К слову сказать в версии 2009 и отмена закрытия склада происходит в параллельном режиме.
Как мониторить процесс закрытия склада?
Самый правильный способ мониторить закрытие склада –сразу после того как это закрытие было запущено, открыть в соседнем окне еще одного клиента DAX и залезть с помощью браузера таблиц в таблицу inventCostListTrans
Если отсортировать записи в этой таблице по номеру итерации, то сразу можно увидеть - какая итерация у вас сейчас идет. Как правило, при сколько-нибудь серьезной логистике, меньше чем итераций за 5-7 склад просто не закрывается. Если у вас склад закрывается за меньшее время, то скорее всего проблемы производительности этой процедуры вас просто не волнуют и вы можете пропустить остаток этого раздела. В течении этих самых первых 5-7 итераций, количество записей в таблице inventCostListTrans резко падает (обычно – с нескольких тысяч до пары сотен или даже нескольких десятков). После того, как эти итерации прошли – есть смысл начинать пристально следить за содержимым этой таблицы. Допустим – вы заметили пару лотов, по которым коррекция себестоимости в поле adjustment с каждой итерацией падает как-то уж слишком медленно. Скажем – если коррекция равняется 600 рублям и с каждой итерацией она уменьшается всего на 10 копеек – самое время попытаться понять – не случилось ли по данной номенклатуре какой-то беды с данными. Скорее всего – причина такого медленного прогона себестоимости состоит в том, что у вас остаток по данной номенклатуре в какой-то точке закрываемого периода падал ниже ноля, в результате чего в грАфе прогона себестоимости образовался цикл. Что делать в подобной ситуации ?
Если вы перфекционист или сумма прогоняемой коррекции как-то уж слишком высока (скажем – 6000 при месячном объеме продаж в 6000000), то нужно записать номера проблемных лотов на бумажку, после чего остановить процедуру закрытия склада, отменить незавершенное закрытие склада и начать разбираться с проблемными лотами. Если вы нашли ситуации отрицательного остатка, то нужно их аккуратно отсторнировать, примаркировать (или указать номер возвращаемого лота)неправильное списание к его сторно и попробовать повторить попытку закрытия склада. (Про маркирование и номера возвращаемых лотов подробнее написано в разделе "О возвратах”
Если же вы обнаружили что сумма прогоняемой коррекции небольшая по сравнению с оборотами за период (допустим 500 при обороте в 50000000, то можно просто подкорректировать (в браузере таблиц) поле MinTransferValue в таблице InventClosing. Это то самое поле, в котором хранится максимальная коррекция пропускной способности, заданная вами в начале процедуры закрытия склада. Если вы укажете там значение, большее чем максимальная из оставшихся в прогоне коррекций, то но очередной итерации прогонки себестоимости, зависшие коррекции просто будут списаны на счета прибылей и убытков. На реальный финансовый результат фирмы это не повлияет, но может слегка подпортить картину прибыльности (или убыточности) отдельных продаж.
Вот почему так важно, чтобы оценочная себестоимость списания не слишком сильно отличалась от истинной себестоимости. Ведь если разница была слишком большой, то в случае образования циклов в графе прогонки себестоимости, каждые несколько дополнительных рублей разницы могут обойтись вам в несколько минут дополнительного времени закрытия.
Кроме того, могу посоветовать разработать какой-нибудь отчет, который пробегал бы по открытым проводкам и выдавал сообщение о переходе остатка через ноль. Если вы будете запускать подобный отчет перед каждым закрытием, то у вас появится возможность привести данные в порядок, без необходимости ждать пока закрытие доберется до 20ой итерации.
В заключение хочу отметить, что существуют определенные ситуации, в которых переход остатков через ноль вызван не ошибками в вводе данных, а объективной спецификой бизнеса. В таком случае – единственный способ бороться с производительностью закрытия склада - это корректировка поля MinTransferValue, о которой я писал чуть выше. Конечно – в этом случае мы не сможем получить корректную себестоимость списания по каждой складской проводке, но по большому счету, в такой ситуации эта себестоимость и не будет иметь особого экономического смысла.
О пересчете склада
В DAX имеется не только процедура закрытия склада, которая рассчитывает окончательную себестоимость списания по каждой складской проводке за период (блокируя при этом дальнейшие складские движения в этом периоде), но и процедура пересчета склада. Эта процедура отличается от закрытия склада следующим образом:
1. Сопоставление приходов и расходов строится “в памяти”, то есть – данные о сопоставлении приходов и расходов не записываются в таблицу складских сопоставлений.
2. В случае необходимости корректировки себестоимости по расходной или приходной проводке, запись в inventSettlement создается, но в ней не заполняются сопоставленные количества и суммы. Происходит заполнение только суммы коррекции.
3. Как следствие первых двух пунктов –перед КАЖДОЙ итерацией прогонки себестоимости происходит операция сопоставления "в памяти” приходных и расходных проводок. Это логично – ведь если мы не пишем в таблицы БД данные о сопоставлении, то перед каждой прогонкой себестоимости нам нужно заново создать в памяти данные о сопоставлении, чтобы понять – с каким расходом сопоставлен корректируемый на данной итерации приход.
4. Можно проводить пересчет склада по отдельной номенклатуре или номенклатурной группе. Нужно только помнить о том, что если данная номенклатура списывалась по журналу спецификаций или журналу производства, то коррекция может затронуть и ту номенклатуру, в производство которой была списана данная номенклатура.
5. В отличие от закрытия склада – система не списывает при пересчете склада погрешности округления.
Если мы хорошенько подумаем о смысле 3 пункта, то можно сделать вывод о том, что пересчет склада будет почти гарантировано работать медленнее, чем закрытие. Ведь перед каждой итерацией прогонки себестоимости, мы вынуждены заново проходить стадию сопоставления приходных и расходных проводок. Мы конечно сэкономим немного времени за счет того что мы не тратим на каждой итерации время на запись данных по сопоставлению в таблицу БД, но скорее всего – сэкономленное время будет с лихвой перекрыто дополнительным временем, нужным на повторяющееся сопоставление.
Отмена закрытия склада
Алгоритм процедуры отмены закрытия/пересчета склада достаточно очевиден:
-
Система пробегается по старым (сделанным по закрытию/пересчету) записям в inventSettlement и помечает их как отмененные
-
Система копирует старые записи в новые (то есть записи отмены закрытия), инвертируя знак сопоставленного количества, сопоставленной суммы и суммы коррекции
-
Система вычитает из полей исходной складской проводки сумму сопоставления, сопоставленное количество и сумму коррекции (если сопоставление было сделано по проводке в статусе физической операции - вычитается только сумма коррекции, причем вычитается из физической суммы по проводке)
-
Порожденные складские сопоставления разносятся процедурой разноски складских сопоставлений, похожей на описанную в разделе "Разноска в ГК". До версии 2009 и закрытие и пересчет и коррекция и отмена всех этих процедур выполнялась одним и тем же классом. В версии 2009 классы разноски операции и классы разноски отмены операции разделили. (Точнее говоря - класс разноски отмены отнаследован от класса разноски операции). Это связано с тем что в 2009 версии, процедуры закрытия склада нагружены дополнительной семантикой разноски отклонений (для новой стандартной себестоимости) и непрямых затрат по производственным заказам (для непрямых затрат) и сохранить полностью единую логику для обоих классов стало невозможным.
Наверное, стоит также добавить, что процедуры отмены закрытия склада также используется и для отмены коррекции себестоимости запасов в наличии или себестоимости складских проводок.
Партионная себестоимость
Нигде в Dynamics AX нет специальной настройки для включения режима партионной себестоимости. Тем не менее – если в настройках группы складских аналитик поставить галку "Финансовый склад" для складских аналитик "Номер партии" или "Серийный номер", то при закрытии склада по ЛЮБОЙ модели мы и получим режим партионной себестоимости, поскольку сопоставление приходов и расходов будет идти только в рамках одного номера партии или серийного номера. Разумнее всего, для той номенклатуры, у которой включен партионный учет, ставить модель закрытия склада по FIFO, поскольку с технической точки зрения она быстрее всего работает.
Один лот – одна себестоимость
Архитектура модуля расчета себестоимости в DAX неявным образом предполагает что элементарной единицей списания или приходования себестоимости является один складской лот. То есть – даже если по одному лоту у нас имеется несколько строк в таблице складских проводок, при расчете с себестоимости система все равно будет считать все себестоимость по лоту в целом.
С первого взгляда – подход логичный, но он содержит в себе некую ловушку, в которую регулярно попадают начинающие внедренцы. Допустим – мы включили по одной из номенклатур партионный учет (включаем нужную галку в настройках групп складской аналитики) и у нас имеется две партии товара по 10 рублей (2шт) и 15 рублей (3шт).
Далее, создаем журнал переноса на 5 штук. Как известно, если мы не указали в настройках групп складской аналитики номер партии, как первичную аналитику, то мы можем не вводить номер партии в строки журнала переноса. При выполнении резервирование по такому журналу, система автоматически разобьет приходные и расходные складские проводки, подставив в каждую из них нужный номер партии. Это удобно для пользователей, поскольку позволяет им не задумываться над подбором номера партии, если в данной ситуации нас не волнует то, какие именно партии будут списаны.
Только вот после разноски такого журнала, мы обнаружим, что во всех приходных проводках стоит одинаковая цена - 13 рублей. В момент разноски журнала, система использует себестоимость списания ЛОТА с первого склада в качестве себестоимости прихода на второй склад. Себестоимость списания лота с первого склада – 65 рублей. Соответственно – при расчете себестоимостей прихода по двум складским проводкам данного лота будет использоваться эта сумма, которая будет распределена между приходными складскими проводками пропорционально их количествам. Закрытие склада не исправит ситуацию, поскольку коррекция себестоимости в таблице InventCostListTrans также привязана к номеру лота, соответственно – на стадии закрытия коррекция будет распределена по приходным проводкам пропорционально их количествам. Вот именно в такой ситуации и возникают жалобы на тему "Аксапта испортила мою себестоимость".
Когда я первый раз столкнулся с подобной ситуацией, я с наскока пытался решить ее, переделав процедуру разноски журнала переноса и закрытия склада. Только вот оказалось, что не очень понятно – как решать эту задачу в общем случае. Например – мы ведь можем по переносу списывать несколько партий и создавать из них одну. Как мы вообще должны обрабатывать ситуацию, при которой у нас в результате переноса меняется не только аналитика физического склада (например - склад или номер ячейки), но и аналитика финансового склада?
Возникновение подобной ситуации, говорит о попытке решить бизнес-проблему айтишным путем. Ведь если вдуматься – ситуация абсурдная: С одной стороны - бухгалтерия пытается вести партионный учет. С другой стороны – бизнес-процессы организованы так, что логистики не знают или не хотят знать – какой номер партии им подставлять и пытаются добиться, чтобы эти номера система подставляла автоматически. В такой ситуации, существует два варианта решения проблемы:
1. Можно настаивать на том, чтобы пользователи вводили номера партий в ручную. В такой ситуации спонсор проекта со стороны заказчика должен жестко разъяснить пользователям – почему так важна партионная себестоимость.
2. Можно настаивать на том, чтобы бухгалтера перешли на использование модели FIFO. Если уж все так хотят чтобы система автоматически подставляла номера партий – так пусть и подставляет. Если аналитика "Номер партии" не будет указана как аналитика финансового склада, то после закрытия склада мы и получим информацию, связывающую расходы с номерами партий в приходах. Только в данной ситуации у нас в складской аналитике расходных проводок не будет номеров партий; Нам придется собирать эту информацию из таблицы складских сопоставлений, связывающей расходы с приходами.
Складские сопоставления и как с ними работать.
В данном разделе пойдет речь о таблице складских сопоставлений (inventSettlement). Строго говоря – использование термина "сопоставление” (Settlement) в названии этой таблицы, поскольку, эта таблица несет двоякий смысл: она может описывать и сопоставление прихода с расходом, и коррекцию себестоимости. Хотя для расходных складских проводок коррекция себестоимости ВСЕГДА порождается на основании сопоставления, для приходных складских проводок коррекция себестоимости происходит совершенно независимо от сопоставления с расходными. Кроме того – если коррекция себестоимости расхода делается на основании пересчета, а не закрытия склада, то коррекция себестоимости будет помещена в эту таблицу без данных о сопоставленном количестве. Давайте внимательнее рассмотрим список полей этой таблицы:
|
Поле |
Описание |
|
TransRecId |
Ссылка на складскую проводку к которой относится данная запись |
|
InventTransId |
Номер лота, по которому прошла коррекция/сопоставление. |
|
Itemid |
Код номенклатуры по которой прошла коррекция/сопоставление |
|
ItemGroupId |
Номенклатурная группа номенклатуры по которой прошла коррекция/сопоставление |
|
TransDate |
Дата коррекции/сопоставления |
|
Voucher |
Документ ГК, по которому прошла коррекция/сопоставления |
|
SettleTransId |
Идентификатор коррекции сопоставления. По большому счету – некий внутренний счетчик. Поле очень любопытно в том случае, если данная запись была порождена закрытием склада. В этом случае- записи в этой таблице, относящиеся к расходной и приходной проводке будут иметь одинаковое значение этого поля. |
|
QtySettled |
Сопоставленное количество. В том случае если данная запись порождена корректировкой прихода или корректировкой расхода, порожденной пересчетом (не закрытием) склада, то данное поле будет пустым. |
|
CostAmountSettled |
Сопоставленная сумма. В том случае если данная запись порождена корректировкой прихода или корректировкой расхода, порожденной пересчетом (не закрытием) склада, то данное поле будет пустым. |
|
CostAmountAdjustment |
Сумма коррекции. Если в результате сопоставления при закрытии склада коррекция себестоимости расхода отсутствовала – поле нулевое. Если запись связанна с приходом и порождена закрытием склада – поле нулевое. |
|
BalanceSheetAccount |
Складской счет, на который будет разнесена данная коррекция |
|
OperationsAccount |
Коррсчет, на который будет разнесена данная коррекция. Обычно – счет затрат (operations) |
|
BalaceSheetPosting |
Тип разноски в ГК, который будет использоваться при разноске на складской счет |
|
OperationsPosting |
Тип разноски в ГК, который будет использоваться при разноске на корсчет. |
|
Dimension |
Финансовая аналитика которая будет использоваться при разноске в ГК |
|
Canceled |
Признак отмены данного сопоставления. Если вы отменяете закрытие или пересчет склада - у исходного складского сопоставления в это поле ставится true. Фактически – это признак сторнирования сопоставления |
|
SettleModel |
Принцип сопоставления. В первом приближении – соответствует складской модели. |
|
Posted |
Признак того, что информация по данной строке была обработана модулем разноски в ГК |
|
SettleType |
Тип сопоставления. |
При выполнении закрытии склада информация о сопоставлении заносится в эту таблицу следующим образом: и для сопоставляемого расхода и для сопоставляемого прихода создается запись в таблице складских сопоставлений, при этом поле SettleTransId у этих двух записей будет одинаковым.
В случае коррекции себестоимости прихода (например – при разноске накладных расходов по накладной или переоценке складских запасов) – создается одна запись. Аналогичным образом – одна запись создается и при коррекции себестоимости расходных проводок (при пересчете склада).
Поля, связанные с разноской в ГК заполняются информацией из таблицы складской разноски (InventTransPosting), связанной с корректируемой (сопоставляемой) складской проводкой. Если запись в этой таблице по каким-то причинам отсутствует – в качестве складского счета берется счет складского прихода или расхода из таблицы настроек складской разноски по данной номенклатуре, в качестве корсчета – счет прибылей и убытков из той же таблицы. Отмечу что в саму таблицу inventTransPosting информация попадает из финансовой аналитики исходного документа и остается в данной таблице даже если этот документ удален.
Надо сказать – что далеко не всегда коррекция себестоимости приводит к необходимости делать проводки в ГК. Скажем – при коррекции себестоимости прихода или расхода по журналу переноса никакой проводки в ГК делать не надо – поскольку по исходному журналу – такой проводки тоже не было. Этот момент отслеживается с помощью поля isPosted в таблице InventTransPosting. Если данное поле не было установлено в true, то счета и корсчета в inventSettlement не заполняются и подсистема разноски сопоставлений в ГК эти коррекции/сопоставления игнорирует. Так что если вы занимаетесь выверкой проводок в ГК по закрытию с себестоимостью, то следует игнорировать записи с пустыми счетами и корсчетами. Наконец – хочу уточнить что поле posted в таблице inventSettlement не имеет никакого отношения к факту разноски или неразноски данного сопоставления(коррекции) в ГК. Это поле заполняется в момент обработки сопоставления классом разноски сопоставлений в ГК и говорит только о том, что эта запись была обработана этим классом.
Немного о складских проводках
Имеет смысл рассказать о тех полях в складских проводках, которые относятся к себестоимости и закрытию склада.
|
Поле |
Описание |
|
CostAmountPosted |
Для приходных складских проводок – себестоимость прихода (в случае закупки – без учета накладных расходов). Для расходных проводок – оценочная себестоимость списания |
|
CostAmountAdjustment |
Сумма корректировки себестоимости. ВСЕГДА должна равняться сумме поля costAmountAdjustment складских сопоставлений, связанных с этой проводкой. |
|
CostAmountSettled |
Сума сопоставленной по закрытию склада себестоимости. У закрытых складских проводок – равняется сумме costAmountPosted и costAmountAdjustment |
|
Qty |
Количество по складскому документу. Всегда считается в тех единицах измерения, которые были указаны как единица измерения склада |
|
qtySettled |
Сопоставленное по закрытию склада количество |
|
costAmountPhysical |
Себестоимость по физическим операциям (попросту говоря – по отборочным накладным). Для проводок списания – почти всегда равняется оценочной себестоимости. Для приходных проводок – себестоимости из приходного документа. Вообще – использовать значения из этого поля для каких-то отчетов – дурной тон. Оно предназначено чтобы ПРИБЛИЗИТЕЛЬНО (плюс-минус трамвайная остановка) оценить складские движения по которым не было еще проведено реальное финансовое складское движение. |
|
CostAmountStd |
Стандартная себестоимость, для данной номенклатуры. Если для данной номенклатуры не включен в группе складских моделей флажок стандартной себестоимости – поле нулевое. |
|
CostAmountOperations |
Для расходов – не заполняется. Для приходов – почти всегда равняется costAmountPosted с обратным знаком. Единственное исключение – закупка номенклатуры, у которой выключен в группе складских моделей флажок "Разносить финансовые операции”. В этом случае – в costAmountPosted пишется ноль, а в costAmountOperations – закупочная себстоимость. В общем случае – в этом поле хранится сумма по корсчету складской операции. |
|
ValueOpen |
Признак того – закрыта данная складская проводка или не закрыта. Закрыта может быть только финансовая складская проводка. Проводка помечается как закрытая только в том случае, если значение costAmountSettled равняется истинной себестоимости (сумме полей costAmountPosted и costAmountAdjustment) и разница между qty и qtySettled меньше чем 0.00000001 |
|
DateClosed |
В момент когда проводка помечается как закрытая, система автоматически заполняет это поле датой последнего складского сопоставления, связанного с данной складской проводкой. |
О возвратах
В системе существует два принципиально разных механизма создания возвратов.
· Для возврата списаний, используется механизм под названием "номер возвращаемого лота”. Этот номер можно указывать, например, в строках заказов или складских проводок. Затем – этот номер возвращаемого лота копируется в складскую проводку по данному возврату (в поле inventTransIdReturn). В момент закрытия склада, наткнувшись на проводку прихода, у которой это поле заполнено, система на итерации прогона себестоимости корректирует себестоимость данного прихода до себестоимости возвращаемого расхода (естественно – с обратным знаком).
· Для возврата приходов используется механизм маркировки складских проводок. Именно об этом механизме я и расскажу поподробнее в оставшейся части раздела.
Итак – система позволяет примаркировать приходные и расходные проводки друг к другу. При этом, в связанные приходные и расходные проводки в поле inventrefTransId записывается ссылка на связанную проводку. При закрытии склада или пересчете, подобные примаркированные проводки не попадают в стандартные процедуры сопоставления приходных и расходных проводок и прогонки себестоимости. Вместо этого, подобные проводки сопоставляются непосредственно друг с другом независимо от используемой складской модели. Как следствие этого – себестоимость списания расходной проводки становится гарантировано равной себестоимости приходной проводки. Следует отметить, что и при маркировании, и при обработке примаркированных проводок в момент закрытия или пересчета склада, система проверяет совпадение складской аналитики финансового склада. То есть – если у вас, например, номер партии является аналитикой финансового склада, то примаркировать проводки с разными номерами партий вам не удастся. Даже если каким-то образом (например – модификацией полей в inventTrans напрямую) подобные проводки будут примаркированы друг к другу, то в момент закрытия/пересчета склада, система отменит подобные маркировки, очистив поле inventRefTransId в складских проводках.
Маркировать проводки можно как до их финансовой разноски, так и после. Нельзя маркировать открытую складскую проводку к закрытой, поскольку в момент закрытия/пересчета склада такие проводки не будут сопоставлены и смысл в маркировании теряется.
К сожалению, кроме расчета себестоимости, маркировка проводок используется в DAX и для других целей:
1. При резервировании в заказанных, маркировка позволяет связать данный резерв в заказанных с конкретной приходной проводкой в статусе "Заказано”. В дальнейшем – при складском или финансовом оприходовании этой складской проводки, именно примаркированная к ней расходная проводка будет переведена в статус "Зарезервировано”. Таким образом – мы можем привязать наш резерв в заказанных к конкретному приходу.
2. При работе модуля сводного планирования, маркировка используется для организации связи данных покрытия чистых потребностей со складскими проводками. Грубо говоря – если две складских проводки примаркированы друг к другу, то запись о данном приходе в таблице чистых потребностей (reqTrans) будет рассматриваться как покрывающая для записи по данному расходу. Аналогично – если мы будем создавать перенос или закупку на основании созданных при сводном планировании планового переноса или закупку, то проводки по данной закупке/переносу будут примаркированы к той расходной проводке, на основании которой появилась данная потребность.
Следует помнить о наличии данных механизмов, поскольку может возникнуть ситуация, когда последствия их работы (примаркированные проводки) фактически выпадут из стандартной процедуры расчета себестоимости о складской модели. При этом – фактически система начнет работать в режиме партионного учета, поскольку себестоимость конкретного расхода будет однозначно определятся себестоимостью конкретного расхода. (Вместо усреднения или расчета по модели FIFO например).
О списании ошибок округления и корректировок при прогонке себестоимости.
Представим себе следующую ситуацию: Допустим – мы закупили 3 единицы товара на общую сумму 10 рублей. Затем – каждую из этих единиц мы продали (отдельными заказами). Предположим также, что мы этот товар не переносили между складами и вообще никаких операций по нему кроме этой закупки и трех продаж, не выполняли. После закрытия склада – себестоимость списания по каждому из этих заказов будет равняться 33 рубля и 3 копейки. По приходу у нас возникнет интересная картина. Сопоставленное количество – будет равняться 3 (то есть – в общем-то, все списали и приходную проводку пора помечать как закрытую). В то же время – сопоставленная сумма будет равняться 9 рублям и 99 копейкам (то есть – приходную проводку нельзя помечать как закрытую, поскольку на проводке зависло сальдо в одну копейку). В подобной ситуации, система просто переоценит приходную проводку на одну копейку в корреспонденции с корсчетом прихода со счетом прибылей и убытков из настроек складской разноски для склада. (Следует отметить – что для закупок, корсчетом прихода является счет потребления по закупке из настроек складских разносок). То есть – после закрытия склада – у нас в приходной проводке в поле costAmountPosted будет указана исходная сумма (10 рублей), а в costAmountAdjustment - -1 копейка, при этом сама приходная проводка будет помечена как закрытая.
В том случае, если у нас происходит списание прогоняемой коррекции себестоимости (либо потому что она меньше заданного при закрытии склада порога точности, либо потому что у нас исчерпался счетчик итераций), система поступает аналогичным образом.
Допустим – у нас с предыдущей итерации прогона себестоимости на данный приход по журналу спецификации пришла коррекция в 3 копейки, которая меньше чем наш порог точности закрытия (Параметр закрытия – "Минимальная коррекция пропускной способности”. Система сгенерирует сопоставление, корректирующее себестоимость прихода по журналу спецификации в корреспонденции с корсчетом прихода на 3 копейки, а затем сразу же уценит этот приход на три копейки в корреспонденции со счетом прибылей и убытков.
Update: Уже после того как опубликовал первую версию статьи - посмотрел как сделаны округления на 4ой версии. Картина следующая: в версии 4.0sp1 в метод initInventSettlement класса inventCostItemDim добавлен новый (последний) параметр _errorAdjustment, который выставляется в true, в том случае если этот метод вызывается из метода createErrorAdjustment, занимающегося списанием ошибок округления и корректировок при пригонке себестоимости. В этом случае, в качестве коррсчета корректировки берется счет прибылей и убытков из настроек складской разноски для данной номенклатуры, а не коррсчет прихода, как обычно. В старой версии, в которой эта логика не была добавлена, списанные округления и корректировки зависали на коррсчетах прихода. Поскольку коррсчетов прихода в закрытии склада использовалось много, оценить и списать сумму ошибок при закрытии было нелегко. Поэтому, если вы работаете не более старых версиях, я рекомендую вам перенести эту доработку на ваше приложение. Кроме того, на мой взгляд, мысль списывать округление напрямую на счета прибылей и убытков тоже не очень удачная. Правильнее было бы накапливать сумму ошибок на каком-то выделенном счете, а потом, при трансформации баланса, закрывать этот счет в ручную. Для того чтобы добиться такого эффекта - необходимо подправить метод inventAdj::errorAccountOperation(), таким образом чтобы он возвращал нужный вам счет ошибок округления. Я бы, наверное, использовал для этого счета отклонений от стандартной себестоимости. Если standard costing используется - то на эти счета как раз и нужно отклонения списывать, а если не используется - то эти счета в настройке складских разносок не заняты и их можно приспособить под списание ошибок и округлений. Если эта схема вам подходит - достаточно поменять в методе InventAdj::errorAccountOperation() значения InventAccountType::InventProfit и InventAccountType::InventLoss на InventAccountType::InventStdProfit и InventAccountType::InventStdLoss соответственно.
Со времен написания оригинальной статьи, группа российской локализации добавила в настройках складских разносок специальный счет для списания округлений. Теперь туда можно поставить какой-нибудь подходящий счет (например - какие-нибудь субсчета 76ого, 91ого или даже 26ого) и в конце периода как-то закрывать накопившуюся погрешность округления.
Стандартная себестоимость.
Существует мнение, что закрытие склада игнорирует те номенклатуры, у которых в складской модели включен режим стандартной себестоимости. Это не так. Более того – если у нас за последнее время менялась стандартная себестоимость по данному изделию, то закрытие склада, например, по средней, усреднит себестоимость старых и новых приходов (сделанных по разным стандартным себестоимостям). Поэтому – очень рекомендуется (не с точки зрения целостности системы, а с точки зрения методики учета), при любом изменении стандартной стоимости изделия, проводить переоценку запасов таким образом, чтобы себестоимость запасов после переоценки равнялась их количеству, помноженному на новую стандартную стоимость.
Кроме того, хочу уточнить, что когда система списывает при приходе разницу между закупочной стоимостью и стандартной, она выполняет эту операцию как стандартную процедуру переоценки приходной складской проводки в корреспонденции со счетом отклонений. При этом – в costAmountPosted попадает закупочная стоимость, в costAmountAdjustment – сумма отклонения, ну и в costAmountStd – стандартная себестоимость (которая будет равнятся сумме закупочной себестоимости и отклонения).
В версии 2009 реализована полностью новая модель работы со стандартной себестоимостью. Та модель, которую я здесь описываю, осталась, но переименована в "Fixed Receipt Price".
Закрытие склада по услугам.
Надо заранее сказать, что настройка работы с услугами в Dynamics AX имеет некоторую неоднозначность.
1. Существует тип номенклатуры "Услуга”. Для номенклатур данного типа система не ведет записей в таблице запасов в наличии (inventSum), по ним нельзя выполнять операцию резервирования, в общем – система в целом не позволяет делать те операции, которые нельзя выполнять по тем сущностям, которые нельзя положить на склад.
2. Существует галка "разносить финансовые операции” в настройках складских моделей. Если эта галка выключена (а для услуг она в 99% случаев отключается), то при приходе данной номенклатуры по закупке, ее себестоимость относится на счета затрат. Во всех остальных вариантах приходов – никаких проводок по номенклатуре с данной складской моделью вообще не делается.
Соответственно – особого смысла закрытие склада для услуг никогда не имело. Собственно – закрытие склада и необходимо для того, чтобы мы могли посчитать точную себестоимость списания в затраты тех активов, которые мы когда-то отнесли на инвентарные счета. Услуги мы и так сразу списали на затратные счета. Возникает законный вопрос – зачем тратить время на складские сопоставления, если себестоимость по ним мы считать не будем ? В версии 4.0 (по крайней мере – в русской версии 4.0) закрытие склада по услугам было отключено. То есть – при выполнении закрытия склада – для всех номенклатур типа услуга сопоставленное количество автоматически приравнивается общему, а в таблицу складских сопоставлений пишется складское сопоставление с пустыми финансовыми суммами и моделью сопоставления "Складское сопоставление номенклатуры по услуге”.
Нужно помнить об этой особенности и если у вас на проекте использовалась номенклатура типа услуга с ВКЛЮЧЕННОЙ галкой "Разносить финансовые операции”, то нужно эту номенклатуру переделать из типа “услуга” в тип “Номенклатура". Впрочем – на реальных внедрениях, я случая подобной настройки не видел.
Update: После некоторых размышлений, я все-таки вспомнил ситуацию, при которой для услуг включалась галка "Разносить финансовые операции". Это делалось для тех услуг, которые включались в состав спецификации. При приходовании услуги делалась проводка Д20.промежуточный К60, а при сборке спецификации с данной услугой - Д20.производство К20.промежуточный. Вот такое услуги при переходе на версию 4.0 однозначно придется переделывать в номенклатуры, иначе их себестоимость просто не будет включена в себестоимость выпущенной готовой продукции.
Почему возникает отрицательный складской остаток?
Наверное все знают, что в Dynamics AX существуют настройки складской модели, разрешающие списание товара, до его приходования на склад. (“Отрицательный физический склад” и “отрицательный финансовый склад”). Хотя время от времени этот режим включают осознанно (например – у складской модели для услуг), но в большинстве случаев – этот режим сознательно выключен. Поэтому – начинающие консультанты очень часто недоумевают, обнаружив, что при выключенном режиме отрицательного склада, складской остаток, тем не менее, опускался ниже ноля на какой-то момент времени.
Это вызвано тем, что в момент выполнения списания (физического или финансового) система контролирует ТЕКУЩИЙ складской остаток. Поэтому – если товар пришел только вчера, а списание мы выполняем более ранней датой, система разрешает это сделать.
Почему так сделано ? Я, на одном из своих проектов, переделывал проверку количества при списаниях. Мне пришлось написать код, который проверяет остаток на складе (по финансовым складским операциям) на дату списания, а затем пробегает по ВСЕМ списаниям и приходам, произошедшим ПОСЛЕ выполненного списания. В том случае, если списание проходило текущей датой, система выполняла операцию чуть медленнее, чем до этой переделки. В то же время, если операция выполнялась, скажем, датой трехнедельной давности – задержка была гораздо более ощутимой – где-то процентов на 40-50, по сравнению со стандартной проверкой. Кроме того – в такой ситуации проверка остатков за период порождала достаточно много блокировок. Когда же я попытался реализовать подобный режим и для физических складских операций, я столкнулся с еще большей проблемой. Не понятно, что в этом случае делать с резервами. Может возникнуть ситуация, при которой менеджер по продажам СЕГОДНЯ поставил резерв под заказ, а система ему не дает проводить отгрузку по заказу задним числом, потому что на тот момент – на складе такого количества товара не было. В общем – на этом проекте я сделал контроль остатка по финансовым операциям и оставил старую проверку для физических операций. Поскольку списания задним числом на этом проекте происходило достаточно редко – проблем подобный подход не вызвал. Но в общем случае полную проверку остатка в реальном времени не сделать. Правильнее будет периодически проверять наличие отрицательного остатка на дату с помощью какого-нибудь отчета.
Оценочная себестоимость.
В общем случае – оценочная себестоимость рассчитывается как “мгновенная средняя» то есть текущий остаток в валюте для данной номенклатуры в разрезе аналитик финансового склада, деленный на текущее количество данной номенклатуры на складе в разрезе тех же аналитик. При этом – в расчет берутся только те количества и суммы, которые были проведены по накладной (но не по отборочной накладной).
В целом - вопрос точности расчета системой не является особо критичным. Чем меньше разница между истинной и оценочной себестоимостями – тем быстрее работает закрытие склада. Если у нас на складе лежит номенклатура, закупленная по цене 400, 600 и 700 рублей, то даже если мы каким-то образом разочек списали одну штуку по мгновенной себестоимости 1200 рублей, ничего страшного не произойдет. В худшем случае – у нас чуть дольше будет работать процедура закрытия склада. В тоже время , если у нас в такой ситуации списалось по оценочной стоимости в 100000000 рублей – то на время закрытия склада это может повлиять достаточно сильно и негативно. Кроме того,надо помнить, что если мы слишком много номенклатуры спишем по какой-то уж совсем бредовой оценочной себестоимости , то у нас может возникнуть ситуация при которой у нас на складе осталось 3 штуки изделий по себестоимости минус 600 рублей. Вылечить подобную ситуацию можно только закрытием или пересчетом склада.
Наконец, надо разобрать несколько специальных случаев. В том случае, если в настройках группы складских моделей установлена галка "Включать физическую себестоимость», то в расчет мгновенной средней включаются суммы и количества, проведенные не только по обычным накладным, но и по отборочным. Если у нас между оформлением отборочной накладной и обычной накладной имеется большой временной лаг, то включение этого режима позволяет несколько увеличить точность расчета мгновенной средней.
В том случае если при расчете мгновенной средней, выяснилось что на складе нет данной номенклатуры и мы не можем вообще посчитать среднюю мгновенную себестоимость ,то система пытается использовать вместо мгновенной средней, то значение стандартной цены из номенклатурной карточки (то есть – тоже самое поле что и для стандартной себестоимости).
Отдельным случаем является работа в режиме стандартной себестоимости (в версии 2009 это называется "Fixed Receipt Price"). В этом случае – вместо вычисления мгновенной средней, используется стандартная себестоимость, указанная в номенклатурном справочнике в поле "Цена» группы полей "Затраты». (В версии 3.0 эта группа полей называлась "Склад»). В принципе – эту цену можно настраивать не только в разрезе номенклатуры, но и для сочетания номенклатурных аналитик по данной номенклатуре. Но это – тема для отдельного обсуждения.
В том случае, если система рассчитывает себестоимость списания для возврата, то для расчета себестоимости списания используется себестоимость того прихода, по которому происходит возврат. При этом для определения ситуации возврата используется либо механизм маркировки проводок, либо указание возвращаемого лота.
"Странные проводки" по возврату закупок.
Часто приходится слышать жалобы начинающих консультантов, на "странные проводки" по возврату закупки. Скажем что-то типа "Почему по закупке у нас прошли проводки Д 10 К 60 1400руб, а по возврату Д 10 К 60 -1400руб; Д10 К10 -200руб?. Откуда вторая проводка?".
Вот причина этой ситуации: В проводки по поставщику мы должны поставить сумму возврата (1400рублей). В тоже время, при отсутствии маркирования, и оценочная и истинная себестоимость списания у нас может отличаться от этих 1400 рублей (В нашем случае – оценочная себестоимость – 1200 рублей). Вот DAX и пытается побороть эту проблему следующим способом:
1. Со складского счета на счет задолженности списывается сумма возврата (количество, помноженное на цену)
2. Складской счет дооценивается (или уценивается) на сумму разницы между мгновенной себестоимостью и суммой возврата, в корреспонденции со счетом потребления из настроек складских разносок. По какой-то непонятной причине, принято в это поле настройки разноски прописывать обычный складской счет, тот же самый что и в настройке счета прихода. Поэтому и появляется странная проводка Д 10 К 10.
Правильнее было бы прописывать в качестве счета потребления прописывать какой-нибудь рабочий счет типа 76.xxx. Тогда разноска возврата имела бы более понятный вид:
Д10 К60 -1400
Д76 К10 -200
В конце периода, после закрытия склада, у нас на счете 76.xxx накопился бы финансовый результат по нашим возвратам. Например – если мы регулярно ухитрялись возвращать поставщику залежалый товар выше себестоимости – у нас бы там накопилось кредитовое сальдо, в обратной ситуации – кредитовое. В конце периода этот счет я бы закрывал на прибыли и убытки, показывая корректировку финансовых результатов периода за счет возвратов поставщику.
Более того, если мы после разноски возвратов смогли примаркировать их к исходным закупкам (то есть – все возвраты прошли в том же периоде что и закупки), то после закрытия склада, у нас вообще не будет сальдо на этом счете, поскольку проведенные по закрытию склада коррекции отреверсируют все проводки со складского счета на счет потребления.
Новая стандартная себестоимость.
Вообще говоря - в версии 2009 был реализован целый комплекс изменений в системе расчета себестоимости, в первую очередь связанных с необходимостью поддержки правильной МСФОшной стандартной себестоимости. Часть из этих изменений, влияет не только на стандартную, однако чтобы не распылять материал по статье, я соберу описание всех этих новшеств в одном разделе.
Я не успел применить новый механизм на практике, так что все нижеописанное было собрано на основании анализа исходных текстов. Вполне возможно что я где-то ошибся в деталях. Относитесь к этому разделу как к путеводителю по концепциям новой функциональности, а не как к руководству пользователя.
Прежде чем двигаться дальше, замечу что старая стандартная себестоимость и ее механизмы остались на месте и включаются галочкой "Fixed receipt price" в настройках складской модели. Новая стандартная себестоимость включается выбором значения "Standard cost" в поле "Inventory Model" группы складских моделей.