AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: База знаний и проекты
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 28.03.2007, 11:50   #1  
Blog bot is offline
Blog bot
Участник
 
25,617 / 848 (80) +++++++
Регистрация: 28.10.2006
Denis Fedotenko: Себестоимость и закрытие склада
**** Обсуждение обновленной версии статьи denisfed: Обновление статьи о закрытии склада. ****


Источник: http://blogs.technet.com/denisfed/ar...23/705202.aspx
==============

О чем все это?

По моему опыту общения с консультантами и разработчиками, внедряющими DAX, вопросы,связанные с закрытием склада и расчетом себестоимости, стали одними из самых больных на внедрениях. Люди относятся к закрытию склада как к черному ящику, который в зависимости от фазы луны выдает самые разнообразные результаты и отрабатывает за самое разное время. На мой взгляд – это вызвано тем, что информация по процедуре расчета себестоимости разбросана по разным местам документации, кроме того некоторые тонкости этой процедуры вообще нигде не описаны и их приходится изучать методом проб и ошибок или изучая исходные тексты процедуры закрытия склада.
В данной статье я попытался дать достаточно подробное объяснение того, как работает данная процедура и разобрать некоторые другие темы связанные с себестоимостью. Часть из приведенной информации собрана из различной документации по DAX, часть получена на основании опыта работы с Axapta 3.0 и разбора ее исходных текстов. На версии 4.0 я всю собранную информацию не перепроверял, но судя по анализу исходных кодов закрытия склада новой версии – серьезных изменений в алгоритме не произошло.
Документ рассчитан на достаточно опытных консультантов и архитекторов DAX, уже знакомых с основными идеями модуля торговли, уже потренировавшимися несколько раз в процедуре закрытия склада и накопивших вопросы по данной тематике.

Зачем вообще нужно закрытие склада?


Основной задачей процедуры закрытия склада является вычисление истинной себестоимости списания номенклатуры. DAX работает с себестоимостью следующим образом: В момент выполнения операции списания, система не пытается точно сосчитать себестоимость списания по данному складскому движению в соответствии с настройками складской модели. Вместо этого, система списывает некоторую оценочную себестоимость, в целом – более или менее похожую на истинную себестоимость. (Подробнее – в разделе "Оценочная себестоимость.”) Далее – при выполнении закрытия склада рассчитывается истинное значение себестоимости в соответствии с настройками складской модели. После выполнения расчета истинной себестоимости система рассчитывает коррекцию –разницу между оценочной себестоимостью и истинной. Эта коррекция записывается в таблицу складских проводок и разносится в ГК.Почему так сделано ? В общем случае, в момент выполнения списания, система может не содержать всех данных, необходимых для расчета истинной себестоимости. Например , при работе в режиме отрицательного склада, мы можем списывать номенклатуру до того как ее приход проведен по системе; при использовании модели "средняя за период» невозможно посчитать себестоимость до того момента, как период будет закончен и все приходы будут проведены по системе и так далее; по модели LIFO мы аналогичным образом не можем посчитать себестоимость расхода до тех пор пока у нас не будет проведен последний приход за период и т.д.
Время от времени, начинающие консультанты на внедрении, приходили ко мне с предложением как-то подправить аксапту, чтобы бухгалтера могли руками вводить в документы списания мгновенную себестоимость и в дальнейшем при закрытии склада, система не трогала такие складские проводки и не пыталась рассчитывать по ним истинную себестоимость. Так вот – подобный подход СИЛЬНЕЙШИМ образом противоречит идеологии метода расчета себестоимости, используемой в DAX. Истинная себестоимость списания ВСЕГДА должна рассчитываться системы на основании сопоставления приходных и расходных складских проводок.
После того как система посчитала истинную себестоимость за период, выполнение любых складских движений за этот период запрещается. Это вполне логично – поскольку вставка новых приходов или расходов задним числом, может привести к нарушению логики уже созданных сопоставлений приходов с расходами и появлению некорректной истинной себестоимости. Если нам нужно просто предварительно посчитать себестоимость списания для текущего состояния складских проводок, без блокировки дальнейших складских движений за период, достаточно вместо процедуры закрытия склада запустить процедуру пересчета.

Итак – закрытие склада состоит из следующих этапов:
1. Сопоставление приходных и расходный складских проводок. Расчет первичной себестоимости списания по расходным проводкам.
2. Прогон коррекции себестоимости по графу движения складских запасов
3. Разноска в ГК.
Рассмотрим каждый из этих этапов подробнее.

Сопоставление приходных и расходных проводок


Расчет истинной себестоимости списания в Аксапте всегда производится на основании сопоставления расходной складской проводки с приходной. При этом сопоставление происходит для проводок, с совпадающим кодом номенклатуры и аналитиками финансового склада.
Для модели FIFO или LIFO, правильность такого подхода вполне очевидна: Например если мы купили 2 штуки по 10 рублей и 5 штук по 14 рублей, то для того чтобы посчитать себестоимость списания 3 штук, надо сопоставить их с первым приходом общей суммой 20 рублей и одной штукой из второго прихода – суммой 14 рублей. Таким образом, в нашем примере, себестоимость списания по расходной проводке на 3 штуки составит 34 рубля. В дальнейшем ,я буду оперировать понятиями количества и суммы сопоставления. При этом сумма сопоставления рассчитывается как себестоимость приходной складской проводки на дату закрытия склада помноженная на отношения сопоставленного количества к количеству в исходной проводке. Естественно – сумма сопоставления округляется в соответствии с настройками округления в справочнике валют.
Как сопоставляются приходы и расходы по модели FIFO– интуитивно понятно, поэтому я не буду об этом подробно рассказывать. Единственное что стоит отметить - система не проверяет соответствие порядка приходов и расходов. Скажем – если мы провели по системе закупку изделия 15ым числом, а списание 5ым (предположим, что у нас никогда не было других движений по этому изделию). В этом случае – эти два прихода будут молча сопоставлены по модели FIFO, что вообще говоря – противоречит здравому смыслу. Подробнее о причинах появления отрицательного остатка и негативных последствиях этого явления я расскажу в разделах “Почему возникает отрицательный складской остаток?” и "Прогон себестоимости”
Модели LIFO или LIFO на дату в DAX было бы правильнее назвать LILO (Last In – Last out). Работают они как и FIFO , но только с точностью до наоборот. Система бежит по списку несопоставленных расходов, начиная с самого последнего и сопоставляет с каждым из них самый последний несопоставленный приход. “LIFO на дату” отличается от LIFO тем, что с расходом может сопоставляться только тот приход, который уже был на складе в момент выполнения расхода. Существование двух этих методов вызвано следующим соображением: Представим себе ситуацию, при которой у нас товар закупался 1ым,5ым и 31ым числами, а продавался, допустим, 10 и 18ым числами. С точки зрения строгой бухгалтерской идеи LIFO, у нас гарантировано должен быть списан товар, закупленный 31 числа (Поскольку по LIFO последние приходы списываются в первую очередь). С другой стороны – получается, что у нас отгрузка от 18 числа сопоставляется с приходом от 31ого – что выглядит как-то уж очень не интуитивно. Вот разработчики системы и реализовали эти два подхода, чтобы удовлетворить обе точки зрения. Первый из них – более правилен с бухгалтерской точки зрения , второй – с обывательской.

Теперь рассмотрим сопоставление в режиме "Средняя” и “Средняя на дату”. В давние былинные времена – до выхода версии Axapta 3.0 sp2 (В локализованной версии – этот service pack ,был выпущен под номером 3), в этом режиме КАЖДЫЙ расход периода сопоставлялся с КАЖДЫМ несопоставленным приходом (в случае Средней на дату – с каждым несопоставленным приходом, с датой меньшей или равной дате расхода). Получалось ,что если скажем у нас на начало месяца на складе уже лежали два несопоставленных прихода и еще 6 приходов пришло за месяц, то каждый из расходов (а их у нас, допустим было 40 штук) сопоставлялся с каждым из этих 8 приходов. В результате – у нас в таблице сопоставлений образовывалось 8*40*2 записей (на два результат умножен из за некоторых особенностей архитектуры сопоставления при которой на каждое сопоставление рождается две записи). Нетрудно сделать вывод, что такой рост таблицы не способствовал быстрому выполнению процедуры закрытия. Поэтому в Axapta 3.0Sp2 был реализован некий компромиссный вариант расчета средней себестоимости. Был введен порог для количества или суммы для каждого сопоставления. Грубо говоря - система, при сопоставлении каждого из расхода с приходами, начинает процесс с тех из несопоставленных приходов, у которых больше несопоставленное количество и стремиться сопоставить каждый раз не менее порогового количества. Если по данному приходу или расходу несопоставленным осталось меньше порогового количества – система сопоставляет столько, сколько осталось – независимо от порога. Пороговое количество может быть задано несколькими способами:
1. Можно указать минимальный процент сопоставляемого количества в параметрах закрытия. В этом случае – система будет стремиться сопоставлять в одном сопоставлении не менее чем N% данного прихода.
2. В поле “минимальное среднее количество” номенклатурной карточке
3. В поле "Минимальное среднее количество” параметров модуля управления запасами. Данный параметр работает только для тех номенклатур, у которых не указанное значение по пункту 2.
Наконец – существует еще один способ косвенно ограничить сопоставляемое количество: Указав при закрытии склада минимальную сумму сопоставления, можно заставить систему стремиться не создавать сопоставлений с суммой сопоставления (то есть – долей себестоимости прихода, сопоставленной с расходом в данном сопоставлении) меньше заданного порогового значения.

Таким образом – в обычных ситуациях (закупочная цена не очень сильно меняется за период, закупки происходят значительно реже, чем продажи), алгоритм расчета средней будет давать очень незначительные отклонения от истинной средней стоимости, рассчитанной, грубо говоря, с помощью Excel, делением себестоимости всех несопоставленных приходов на количество. Но если представить себе ситуацию при которой мы обычно закупаем за период 2-3 партии по тысяче штук, продаем несколько тысяч партий по 1-2 штуки, но почему-то в данном конкретном периоде мы внезапно закупили дополнительно одну партию из 5 штук по цене в два раза выше обычной, то есть большие шансы что те несколько расходов , которые будут сопоставлены с этой странной партией будут иметь завышенную себестоимость списания.
Особо отмечу, что при расчете себестоимости для сопоставления используется сальдо приходной проводки на дату закрытия. То есть – если мы закупили товар 15 числом, потом 25 числом доначислили накладные расходы на закупку, то при закрытии склада 20ым числом для расчета суммы сопоставлении будет использоваться себестоимость из исходной закупки – без суммы накладных расходов.

Прогон себестоимости

Итак – сопоставление и приходных и расходных проводок закончен. Истинная себестоимость посчитана. Зачем нужен какой-то дополнительный этап?
Представим себе, следующую ситуацию:
· 1 января закупили номенклатуру на сумму 2000 рублей
· 5 числа – перенесли ее на соседний склад. Очевидно, что мгновенная себестоимость расхода, а вместе с ней и себестоимость прихода на соседний склад составит 2000 рублей
· 10 числа – продали номенклатуру с соседнего склада. Мгновенная себестоимость списания опять-таки составит 2000 рублей
· 20 числа – на первоначальную закупку доначислили расходы за транспортировку в сумме 400 рублей
· Модель FIFO
Если мы закрываем склад 30ым числом, то система у нас сопоставит расход от 5 числа с приходом от 1ого и посчитает истинную себестоимость списания по складскому переносу, равную 2400 рублям. Естественно – возникает задача как-то добиться того, чтобы себестоимость прихода на соседний склад и себестоимость списания с такового по продаже также была скорректирована до 2400 рублей.
Эта задача решается следующим образом:
При любом обновлении расходной складской проводки, система проверяет – нет ли для данного списания, связанного с ним прихода? (Связанные приходы существуют для складских проводок списания, порожденных из журнала переноса;журнала карантинного заказа; заказа на перемещение; производственного заказа; журнала спецификаций. Кроме того – связанный приход существует для тех складских проводок прихода, у которых заполнен номер возвращаемого лота. ) Если данный расход действительно имеет связанный приход, то сумма коррекции записывается в таблицу “Коррекции уровня лота” (inventCostListTrans), вместе с номером лота связанного прихода и некоторой другой служебной информацией.
Далее на стадии прогона себестоимости, система считывает из этой таблицы информацию о корректируемых приходных проводках, проводит коррекцию себестоимости по этим приходным проводкам, а затем корректирует и себестоимости списания в расходных складских проводках, сопоставленных с корректируемой приходной проводкой. Если скорректированные подобным образом расходные проводки, в свою очередь также имеют связанные приходные проводки, то процесс прогона себестоимости повторяется.
Таким образом – процесс прогона себестоимости по сути, является итерационным. Фактически – система через таблицу складских сопоставлений строит граф движения материалов от их начального оприходования до окончательного списания, проходя при этом через все цепочки переноса и сборки номенклатуры.
Как определить число итераций прогона себестоимости, необходимое для полного закрытия склада ? Вопрос сложный. В теории – число итераций прогона себестоимости должно равняться максимальному числу переносов данной номенклатуры между разными складскими аналитиками через журнал переноса, плюс уровень вложенности спецификаций, плюс число переносов номенклатуры через журнал карантинного заказа и тп. В реальности – на число итерации кардинальным образом влияет наличие циклов в графе прогона себестоимости. Если их нет – закрытие отрабатывает за 5-7-10-15 итераций, если они есть, то время, требуемое для полной прогонки себестоимости становится труднопредсказуемым.
Почему в графе прогона себестоимости образуются циклы:
Представим себе следующую ситуацию
1 числа закупили 1 штуку номенклатуры по цене 200 рублей (зак1)
20 числа закупили еще 4 штуки - по цене 250 рублей (зак2)
Потом – задним числом провели 5ым числом перенос 2 штук со склада 1 на склад 2. (пер1)
Потом - задним числом перенесли 6ым числом эти две штуки обратно (пер2)
25 числа – все продали (зкз1)
Ну и наконец – 27ым числом доначислили 20 рублей накладных расходов на первую закупку.
Закрываем склад 31 числом по модели FIFO. Аналитика финансового склада - склад
До закрытия склада имеем следующую картину себестоимостей и количеств в проводках:

<...таблица в исходном сообщении...>

По итогам сопоставления по модели FIFO имеем следующую картину:

<...таблица в исходном сообщении...>

Обратим внимание на то, что у нас в грАфе прогона себестоимости образовался цикл: списание по первому переносу сопоставилось с приходом по второму переносу. А приход по второму переносу, в свою очередь зависит от списания по первому переносу. В поле "Коррекция” для приходов и расходов будет указана сумма коррекции себестоимости, накопленная на данной итерации закрытия склада. Посмотрим - к чему это приведет. Далее – каждая таблица будет соответствовать одной итерации прогона себестоимости:

<...таблица в исходном сообщении...>

Ну и так далее. Если бы у нас не было ситуации с переносом между складами при отсутствии товара на складе, то закрытие склада отработало бы за две итерации. В нашем же примере – на закрытие потребуется порядка 15-20 итераций. Кроме того – можно спрогнозировать, что в итоге у нас себестоимость списания по заказу так и не дотянет до правильного значения в 1270 рублей, при этом дельта будет списана с проводок по переносу в виде округления.
Таким образом, если возникла ситуация при которой в какой-то точке периода, за который мы закрываем склад, возникла ситуация отрицательного складского остатка, то это может привести к чрезмерно большому числу итераций по закрытию склада и недостаточной точности результата. Подробнее про причины этого явления написано в разделе "Почему возникает отрицательный складской остаток?”
Кроме того – стоит помнить, что при использовании модели средней себестоимости за период или на дату, у нас, в общем случае, КАЖДАЯ приходная проводка, сопоставляется с КАЖДОЙ расходной, соответственно - циклы в графе прогона себестоимости образуются даже если складской остаток не падал ниже ноля в течении закрываемого периода.
Поскольку ситуация, при которой закрытие склада длится неопределенно долгое время, случается, к сожалению не так уж редко, в процедуре закрытия склада имеются два параметра, которые позволяют явно или неявно ограничивать число итераций прогона себестоимости.



1. В параметрах закрытия склада имеется поле "максимальная пропускная способность”. Именно в этом поле и указывается максимальное число итераций, которое система может выполнить на стадии прогонки себестоимости. Если при выполнении процедуры прогонки себестоимости добрались до итерации, указанной в этом поле, то при выполнении этой итерации, коррекция себестоимости (пришедшая с предыдущей итерации в таблице InventCostListTrans) по данной приходной проводке не переносится на сопоставленный с данным приходом расход, а списывается с прихода на счет прибылей и убытков.
2. Также в параметрах закрытия склада имеется поле "Минимальная коррекция пропускной способности”. Если значение коррекции себестоимости, пришедшая с предыдущей итерации в таблице inventCostListTrans, меньше этого значения, то эта коррекция не переносится связанный с данным приходом расход, а просто списывается с прихода на счет прибылей и убытков. Хочу подчеркнуть, что этот параметр работает для КАЖДОЙ строки таблицы inventCostListTrans. То есть – если у нас в inventCostListTrans имеется три коррекции на 2,10 и 80 копеек, значение параметра "минимальная коррекция пропускной способности” установлена в 5 копеек, то списание в прибыли и убытки будет выполнено только для первой из коррекций. По остальным коррекциям итерации прогонки будут продолжаться.
Подробнее об списании коррекций – в разделе "О списании ошибок округления и корректировок при прогонке себестоимости.”

Разноска в ГК


Прежде всего, хочу отметить, что разноска в ГК выполняется только в том случае, если в параметрах закрытия склада была установлена галка "Обновить главную книгу». Смысла не устанавливать эту галку я не вижу, поскольку начиная еще с версии Axapta 2.5Sp1Hf1, разноска стала выполняться достаточно быстро по сравнению со всеми остальными этапами закрытия склада и отключение этой галки не приводит к серьезному повышению быстродействия этой процедуры.
На предыдущих этапах закрытия склада была заполнена таблица складских сопоставлений (InventSettlement) в которой помимо собственно сопоставленных количеств, сопоставленных сумм и сумм коррекций находится также информация, необходимая для создания бухгалтерских проводок по выполненной коррекции – счет, коррсчет, аналитика, разноска для счета и коррсчета. Поэтому процедура разноски закрытия склада работает достаточно просто. Она группирует суммы коррекции в разрезе этих бухгалтерских параметров, а потом делает соответствующие проводки в ГК. Поэтому – нет особой необходимости в процедуре, которая бы позволяла выверять проводки в ГК по закрытию склада со складскими проводками. Вся информация по счетам аналитикам и тп находится в таблице складских сопоставлений. Если у вас при закрытии склада сгенерировались проводки в ГК с какими-то неожиданными аналитиками или счетами – ищите эти счета и аналитики в таблице сопоставлений. Ну а из этой таблицы уже можно перейти к исходным складским проводкам и попытаться понять – на основании каких операций были сгенерированы эти странные проводки.
Кроме того – на разноску влияет параметр процедуры закрытия склада, называющийся спецификация. В оригинальной (нелокализованной) версии DAX, этот параметр позволял процедуре разноски группировать проводки не только по бухгалтерским параметрам, но и по коду номенклатуры, по которой была выполнена коррекция или коду ее номенклатурной группы. То есть – даже если операции с разными номенклатурами породили коррекции с одинаковыми аналитиками, счетами и корсчетами, в ГК эти коррекции попадали двумя отдельными проводками. К сожалению – этот режим оказался несовместимым с механизмом корреспонденции счетов, используемым в российской версии DAX. Поэтому – если режим корреспонденции счетов включен, то группировка проводок по номенклатуре или номенклатурным группам невозможна. У меня этот факт не смущает, , поскольку, как я уже сказал, выверять проводки в ГК по процедуре закрытия гораздо удобнее и легче с помощью таблицы складских сопоставлений (inventSettlement).
О параллельном закрытии склада с нескольких рабочих мест.


Наиболее значительным изменением в процедуре закрытия склада со времен выхода первой локализованной версии 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 исключительно как некий внутрисистемный инструмент для взаимодействия между несколькими клиентами, в качестве побочного эффекта – эти таблицы являются прекрасным инструментом для мониторинга процесса закрытия склада. Поэтому прежде чем приступить к обсуждению того, как этот процесс мониторить – давайте посмотрим структуру данных таблиц:

<...таблица в исходном сообщении...>


Самый правильный способ мониторить закрытие склада –сразу после того как это закрытие было запущено, открыть в соседнем окне еще одного клиента 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 пункта, то можно сделать вывод о том, что пересчет склада будет почти гарантировано работать медленнее, чем закрытие. Ведь перед каждой итерацией прогонки себестоимости, мы вынуждены заново проходить стадию сопоставления приходных и расходных проводок. Мы конечно сэкономим немного времени за счет того что мы не тратим на каждой итерации время на запись данных по сопоставлению в таблицу БД, но скорее всего – сэкономленное время будет с лихвой перекрыто дополнительным временем, нужным на повторяющееся сопоставление.

Партионная себестоимость


Нигде в Dynamics AX нет специальной настройки для включения режима партионной себестоимости. Тем не менее – если в настройках группы складских аналитик поставить галку "Финансовый склад" для складских аналитик "Номер партии" или "Серийный номер", то при закрытии склада по ЛЮБОЙ модели мы и получим режим партионной себестоимости, поскольку сопоставление приходов и расходов будет идти только в рамках одного номера партии или серийного номера. Разумнее всего, для той номенклатуры, у которой включен партионный учет, ставить модель закрытия склада по FIFO, поскольку с технической точки зрения она быстрее всего работает.
Один лот – одна себестоимость


Архитектура модуля расчета себестоимости в DAX неявным образом предполагает что элементарной единицей списания или приходования себестоимости является один складской лот. То есть – даже если по одному лоту у нас имеется несколько строк в таблице складских проводок, при расчете с себестоимости система все равно будет считать все себестоимость по лоту в целом.
С первого взгляда – подход логичный, но он содержит в себе некую ловушку, в которую регулярно попадают начинающие внедренцы. Допустим – мы включили по одной из номенклатур партионный учет (включаем нужную галку в настройках групп складской аналитики) и у нас имеется две партии товара по 10 рублей (2шт) и 15 рублей (3шт).
Далее, создаем журнал переноса на 5 штук. Как известно, если мы не указали в настройках групп складской аналитики номер партии, как первичную аналитику, то мы можем не вводить номер партии в строки журнала переноса. При выполнении резервирование по такому журналу, система автоматически разобьет приходные и расходные складские проводки, подставив в каждую из них нужный номер партии. Это удобно для пользователей, поскольку позволяет им не задумываться над подбором номера партии, если в данной ситуации нас не волнует то, какие именно партии будут списаны.
Только вот после разноски такого журнала, мы обнаружим, что во всех приходных проводках стоит одинаковая цена - 13 рублей. В момент разноски журнала, система использует себестоимость списания ЛОТА с первого склада в качестве себестоимости прихода на второй склад. Себестоимость списания лота с первого склада – 65 рублей. Соответственно – при расчете себестоимостей прихода по двум складским проводкам данного лота будет использоваться эта сумма, которая будет распределена между приходными складскими проводками пропорционально их количествам. Закрытие склада не исправит ситуацию, поскольку коррекция себестоимости в таблице InventCostListTrans также привязана к номеру лота, соответственно – на стадии закрытия коррекция будет распределена по приходным проводкам пропорционально их количествам. Вот именно в такой ситуации и возникают жалобы на тему "Аксапта испортила мою себестоимость".
Когда я первый раз столкнулся с подобной ситуацией, я с наскока пытался решить ее, переделав процедуру разноски журнала переноса и закрытия склада. Только вот оказалось, что не очень понятно – как решать эту задачу в общем случае. Например – мы ведь можем по переносу списывать несколько партий и создавать из них одну. Как мы вообще должны обрабатывать ситуацию, при которой у нас в результате переноса меняется не только аналитика физического склада (например - склад или номер ячейки), но и аналитика финансового склада?
Возникновение подобной ситуации, говорит о попытке решить бизнес-проблему айтишным путем. Ведь если вдуматься – ситуация абсурдная: С одной стороны - бухгалтерия пытается вести партионный учет. С другой стороны – бизнес-процессы организованы так, что логистики не знают или не хотят знать – какой номер партии им подставлять и пытаются добиться, чтобы эти номера система подставляла автоматически. В такой ситуации, существует два варианта решения проблемы:
1. Можно настаивать на том, чтобы пользователи вводили номера партий в ручную. В такой ситуации спонсор проекта со стороны заказчика должен жестко разъяснить пользователям – почему так важна партионная себестоимость.
2. Можно настаивать на том, чтобы бухгалтера перешли на использование модели FIFO. Если уж все так хотят чтобы система автоматически подставляла номера партий – так пусть и подставляет. Если аналитика "Номер партии" не будет указана как аналитика финансового склада, то после закрытия склада мы и получим информацию, связывающую расходы с номерами партий в приходах. Только в данной ситуации у нас в складской аналитике расходных проводок не будет номеров партий; Нам придется собирать эту информацию из таблицы складских сопоставлений, связывающей расходы с приходами.
Складские сопоставления и как с ними работать.


В данном разделе пойдет речь о таблице складских сопоставлений (inventSettlement). Строго говоря – использование термина "сопоставление” (Settlement) в названии этой таблицы, поскольку, эта таблица несет двоякий смысл: она может описывать и сопоставление прихода с расходом, и коррекцию себестоимости. Хотя для расходных складских проводок коррекция себестоимости ВСЕГДА порождается на основании сопоставления, для приходных складских проводок коррекция себестоимости происходит совершенно независимо от сопоставления с расходными. Кроме того – если коррекция себестоимости расхода делается на основании пересчета, а не закрытия склада, то коррекция себестоимости будет помещена в эту таблицу без данных о сопоставленном количестве. Давайте внимательнее рассмотрим список полей этой таблицы:

(...таблица в исходном сообщении...)

При выполнении закрытии склада информация о сопоставлении заносится в эту таблицу следующим образом: и для сопоставляемого расхода и для сопоставляемого прихода создается запись в таблице складских сопоставлений, при этом поле SettleTransId у этих двух записей будет одинаковым.
В случае коррекции себестоимости прихода (например – при разноске накладных расходов по накладной или переоценке складских запасов) – создается одна запись. Аналогичным образом – одна запись создается и при коррекции себестоимости расходных проводок (при пересчете склада).
Поля, связанные с разноской в ГК заполняются информацией из таблицы складской разноски (InventTransPosting), связанной с корректируемой (сопоставляемой) складской проводкой. Если запись в этой таблице по каким-то причинам отсутствует – в качестве складского счета берется счет складского прихода или расхода из таблицы настроек складской разноски по данной номенклатуре, в качестве корсчета – счет прибылей и убытков из той же таблицы. Отмечу что в саму таблицу inventTransPosting информация попадает из финансовой аналитики исходного документа и остается в данной таблице даже если этот документ удален.
Надо сказать – что далеко не всегда коррекция себестоимости приводит к необходимости делать проводки в ГК. Скажем – при коррекции себестоимости прихода или расхода по журналу переноса никакой проводки в ГК делать не надо – поскольку по исходному журналу – такой проводки тоже не было. Этот момент отслеживается с помощью поля isPosted в таблице InventTransPosting. Если данное поле не было установлено в true, то счета и корсчета в inventSettlement не заполняются и подсистема разноски сопоставлений в ГК эти коррекции/сопоставления игнорирует. Так что если вы занимаетесь выверкой проводок в ГК по закрытию с себестоимостью, то следует игнорировать записи с пустыми счетами и корсчетами. Наконец – хочу уточнить что поле posted в таблице inventSettlement не имеет никакого отношения к факту разноски или неразноски данного сопоставления(коррекции) в ГК. Это поле заполняется в момент обработки сопоставления классом разноски сопоставлений в ГК и говорит только о том, что эта запись была обработана этим классом.
Немного о складских проводках

(...таблица в исходном сообщении...)

....

Еще: http://blogs.technet.com/denisfed/ar...23/705202.aspx
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору.
За это сообщение автора поблагодарили: AlGol (1), kALVINS (1), alex55 (1), arhat (1).
Теги
faq, закрытие склада, полезное, себестоимость

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Denis Fedotenko: Себестоимость и длинные производственные заказы Blog bot DAX Blogs 13 21.11.2013 16:57
Пересчет и закрытие склада. Jony DAX: Функционал 11 30.03.2010 18:50
InventTransIdReturn и Закрытие склада DenisS DAX: Программирование 15 03.12.2008 09:02
Закрытие склада. Параметр "Спецификация" DenWolf DAX: Функционал 0 05.06.2006 14:46
Закрытие склада в основной и вторичной валюте, отключенная корреспонденция счетов May DAX: Функционал 1 02.04.2004 13:25

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 04:29.