Подробное описание работы механизма расчета себестоимости в программах начиная с версии ERP 2.1.3 (и соответствующих ей версий КА и УТ)

Подробное описание работы механизма расчета себестоимости в программах начиная с версии ERP 2.1.3 (и соответствующих ей версий КА и УТ)

Начиная с версии ERP 2.1.3 (и соответствующих ей версий КА и УТ) различаются два типа движения:

  • "первичные" - формируемые в соответствии с логикой документов при их проведении;
  • "расчетные" - формируемые данным механизмом (идентификатором типа движения является новый реквизит "РасчетСебестоимости" регистров накопления).

Список регистров, обслуживаемых механизмом расчета себестоимости, см. в ИсходящиеДанныеМеханизма()

Регистратором расчетных движений теперь является первичный документ (из реквизита ДокументДвижения), а не документ РасчетСебестоимостиТоваров. Документ РасчетСебестоимостиТоваров больше не делает движений по следующим регистрам: ВыручкаИСебестоимостьПродаж, Закупки, ПрочиеРасходыНезавершенногоПроизводства (есть только в ERP и КА) (документ остается регистратором для этих регистров для обратной совместимости).

При перепроведении документов расчетные движения сохраняются, независимо от внесенных в документ изменений (Для этого в модуле набор записей обслуживаемых регистров размещен специальный код. Для примера см. модуль регистра накопления СебестоимостьТоваров - вызовы процедур этого модуля.). Изменения в документе будут учтены в расчетных движениях при перерасчете себестоимости.

Начиная с версии ERP 2.1.3 изменился алгоритм формирования и записи движений. Теперь по каждому обслуживаемому механизмом регистру движения формируются следующим образом:

  • перед началом расчета старые расчетные движения не очищаются - они остаются в ИБ до окончания расчета;
  • новые расчетные движения, формируемые механизмом, помещаются в таблицу значений;
  • при достижении определенного размера таблицы значений или при окончании очередного этапа расчета;
  • новые движения из таблицы значений перекладываются во временную таблицу;
  • при окончании расчета сравниваются новые (из временной таблицы) и старые (из данных ИБ) движения:
    • перезаписываются движения только у тех документов, у которых есть отличия между старыми и новыми расчетными движениями;
    • только документы с перезаписанными движениями регистрируются к отражению в учете.

    Данные изменения позволяют:

    • посмотреть себестоимость по документу из самого документа - отчетом "Движения документа";
    • при перерасчете себестоимости перезаписывать только реально измененные расчетные движения;
    • регистрировать к отражению в учете только документы с перезаписанными движениями (в ERP и КА).

    Переход на версию ERP 2.1.3 (и соответствующие ей версии КА2 и УТ11)

    При переходе на новую версию ранее сформированные расчетные движения автоматически не изменяются, т.к. для этого нужен не простой перенос движений между регистраторами, а "эмуляция" пересчета себестоимости, что чревато. Если запустить перерасчет старого периода, то в нем будут сформированы корректные движения по новой схеме.

    Запуск расчета себестоимости.

    Точкой входа в алгоритм расчета является процедура РассчитатьВсе() в которую предаются параметры:

    • период расчета - месяц;
    • возможен "облегченный" предварительный расчет себестоимости - позволяет формировать некоторые отчеты (если за указанный период уже был выполнен фактический расчет, то предварительный расчет выполняться не будет);
    • расчет выполняется или по указанному массиву организаций, или по всем организациям, связанным с указанной организацией по схеме Интеркампани (см. СвязиОрганизацийПоСхемеИнтеркампани()):
      • если организация для расчета не указана, то будет выполнен расчет по всем организациям, имеющим в указанном периоде движения по регистрам себестоимости;
      • все организации, по которым выполняется фактический расчет, должны иметь одинаковый метод оценки стоимости запасов (см. ОпределитьМетодОценкиСтоимости());

      // Запуск расчета себестоимости. // (ранее - ВыполнитьРегламентноеЗаданиеРасчетСебестоимости() модуля менеджера документа расчета себестоимости) // // Параметры: // Дата - Дата - период расчета себестоимости // ПредварительныйРасчет - Булево - выполнять фактический или предварительный расчет; // предварительный расчет может выполняться // = регламентным заданием // = как подготовительный этап к распределению расходов на продукцию // Организация - СправочникСсылка.Организации - рассчитывать только по указанной организации; // также будут пересчитана себестоимость по организациям, связанным по схеме Интеркампани с указанной // - Массив - массив организаций, по которым надо рассчитать себестоимость, другие организации не рассчитываются // РегламентноеЗадание - Булево - если Истина, значит вызвана из регламентного задания расчета предварительной себестоимости // ПараметрыОтладки - Структура - предназначена для переопределения одноименных свойств структуры ПараметрыРасчета // (подробнее см. пояснения в коде ИнициализироватьПараметрыРасчета() к параметру ПараметрыОтладки)

      Перед расчетом для каждой организации будет сформирован документ РасчетСебестоимостиТоваров (если его еще не было) со следующим заполнением:

      • в реквизите Организация шапки документа будет указана организация, которой принадлежит данный документ;
      • в табличной части Организации будут указаны все организации, связанные с ней по схеме Интеркампани, в т.ч. и она сама:
        • до версии ERP 2.1.3 (и соответствующих ей версий КА и УТ) такого реквизита шапки не было, а документ расчета себестоимости создавался один на всю группу организаций, связанных по схеме Интеркампани (информация о документах расчета себестоимости в разрезе организаций хранится в общих параметрах расчета - во временной таблице ВТДокументыРасчетаСебестоимости и свойстве ДокументыРасчетаПоОрганизациям).

        Для выполнения расчета без падения в случае возникновении ошибки, есть функция-обертка РассчитатьВсеВПопыткеИсключении() параметры аналогичны процедуре РассчитатьВсе(), но функция возвращает значение - Булево - признак успешного выполнения расчета.

        Выполнение расчета себестоимости.

        Непосредственный расчет выполняется в функции РассчитатьСебестоимостьПоГруппеОрганизаций() Схематически расчет выглядит следующим образом:

        • выполняется инициализация общих параметров для всего алгоритма (см. ИнициализироватьПараметрыРасчета());
        • последовательно вызываются процедуры-этапы расчета (подробнее ниже)
          • некоторые этапы могут быть пропущены из-за настроек системы и/или параметров запуска расчета;
          • результатом выполнения этапа являются сформированные расчетные движени и/или "глобальные" временные таблицы (используемые на следующих этапах);
          • запись может выполняться в несколько потоков, с использованием фоновых заданий (см. свойство "МаксимальноеКоличествоФЗ");

          Структура этапа расчета.

          Схематически процедура-этап расчета выглядит следующим образом:

          • создается запрос выборки исходных данных для этапа; заполняются его свойства; запрос выполняется;
            • если целью этапа является только формирование "глобальных" временных таблиц, дальнейшее к нему не относит;
            • некоторые этапы движений не формируют - формируют только "глобальные" временные таблицы;
            • код формирования движений вынесен в процедуры вида СформироватьДвижения<Имя регистра><Уточнение операции>();
            • внутри этих процедур для добавления движения обязательно используется процедура ДобавитьЗаписьВТаблицуДвижений();
            • при этом также выполняется обновление служебных кэшей оборотов и остатков (подробнее ниже);
            • т.о. в промежутке между выборкой исходных данных и окончанием этапа обращаться к кэшам нельзя - они не актуализированы.

            Обращение к данным ИБ в запросах.

            Поскольку новые расчетные движения по регистрам себестоимости записываются в ИБ только в конце расчета, то в ходе расчета при обращении к таблицам этих регистров (реальным или виртуальным) надо соблюдать некоторые правила (касается только регистров, перечисленных в ИнициализироватьРегистры()). 1. Обороты (движения) регистра за период должны получаться объединением:

            • основной таблицы регистра с отбором "Т.РасчетСебестоимости = Ложь" (первичные движения);
            • временной таблицы ВТКэш<Имя регистра> (новые расчетные движения);

            Для удобства, по некоторым регистрам эти данные автоматически кэшируются во временной таблице ВТКэшЗаписи<Имя регистра>. Список регистров указан в свойстве "РегистрыСРасчетнымиЗаписями" общих параметров расчета.

            2. Остатки регистра (для регистров остатков) на конец периода должны получаться объединением:

            • остатков регистра на начало периода;
            • основной таблицы регистра с отбором "Т.РасчетСебестоимости = Ложь" (первичные движения за период);
            • временной таблицы ВТКэш<Имя регистра> (новые расчетные движения за период).

            Для удобства, по некоторым регистрам эти данные автоматически кэшируются во временной таблице ВТКэшРасчетныеОстатки<Имя регистра>. Список регистров указан в свойстве "РегистрыСРасчетнымиОстатками" общих параметров расчета.

            3. Новые движения, сформированные на предыдущих этапах расчета, хранятся во временной таблице ВТКэш<Имя регистра>. Данная временная таблица создается для всех регистров, обслуживаемые механизмом расчета себестоимости.

            Также имеются ряд дополнительных особенностей работы с запросами (причины: оптимизация, платформа и т.д.).

            1. Данные, используемые для отборов во всех запросах механизма расчета, хранятся

            • в общих параметрах расчета (организации, период, значения функциональных опций и т.п.);
            • в "глобальных" временных таблицах (например, ВТОтборАналитикаПоПартнерам - см. ИнициализироватьВременныеТаблицыДляОтборов()).

            Для установки этих параметров используется универсальная процедура ИнициализироватьСвойстваЗапроса() В результате, все запросы механизма расчета гарантировано используют одинаковые отборы. Эта же процедура устанавливает запросу общий менеджер временных таблиц, в котором хранятся все перечисленные выше таблицы кэшей.

            2. Существует ошибка Платформы 30025997, в результате которой возникают проблемы с полем ВидДвижения во временных таблицах. Для обхода ошибки во всех временных таблицах вида ВТКэш, ВТКэшЗаписи, ВТКэшРасчетныеОстатки вместо стандартного поля ВидДвижения хранится техногенное поле СлужебноеВидДвиженияПриход с типом "Булево" алгоритм работы с ним следующий:

            • в запросах к этим временным таблицам следует обращаться только к полю СлужебноеВидДвиженияПриход;
            • в таблицах значений, в которых предварительно накапливаются новые расчетные записи, есть только стандартное поле ВидДвижения;
            • преобразование поля между таблицей значения и временной таблицей выполняется автоматически, дополнительных действий не требуется.

            Отладка и поиск проблем.

            Для облегчения разработки, тестирования и поиска проблем реализован механизм протоколирования расчета (см. процедуры вида ПротоколРасчета_. ) который отрабатывается по следующим шагам:

            • при начале очередного этапа расчета в журнал регистрации делает запись - для отслеживания прогресса выполнения расчета;
            • при окончании расчета в журнал регистрации выводится подробный протокол расчета.

            Также реализована возможность переопределения некоторых параметров расчета (см. РассчитатьВсе(), параметр ПараметрыОтладки).