Распределение расходов пропорционально продажам.

Программирование - Практика программирования

финансовая модель учет расходов

6
Финансовая модель. Распределение административных расходов по подразделениям пропорционально продажам за месяц.

Для кого: для финансового директора - для понимания, что не Excel'ем единым жив финансовый учет.

Для кого: для программиста - для понимания, как внедрить предлагаемую финансовую модель.

Вашему вниманию представлена статья - пошаговое внедрение в УТ 10.3 финансовой модели, при которой  общие административные расходы текущего месяца распределяются по подразделениям пропорционально продажам каждого подразделения за текущий месяц. 

Подобная финансовая модель не реализована типовым функционалом в УТ 10.3, поэтому потребовалась доработка УТ 10.3. Как и любая модель имеет свои допущения и ограничения. Внедрялась на конкретном предприятии с конкретными бизнес-процессами, и поэтому не претендует на универсальность.

Самое скучное

- разобрать структуру решения на уровне таблиц

Шаг 1. Представьте 4 розничных магазина и 1 бэк-офис администрации. Магазины учитываются как подразделения организации (справочник "Подразделения") (см. рисунок).

В УТ 10.3 не так много разрезов учета: справочники Склады, Подразделения, Организации, Проекты, Кассы, Контрагенты, Договора и т.д. - для каждого вида учета (товарный, финансовый) имеется свой набор так называемых измерений, относительно которых накапливаются показатели в соответствующих регистрах накопления.  Для модели был выбран справочник "Подразделения" в качестве разреза учета - достаточно "популярный" разрез учета (см. рисунок).

Шаг 2. Для учета расходов (финансовых) по подразделениям (магазинам) используется регистр накопления "ДвиженияДенежныхСредств". Распределение административных расходов также учитывается проводками по регистру "Движения денежных средств".

Ни один "денежный" регистр накопления не содержит в своем наборе измерений разрез учета "Подразделение", поэтому был расширен тип значений измерения "Проект" на соответствующий справочник. При этом в настройках учета отключен параметр "Вести учет по проектам" - еще раз, учет по проектам не ведется в программе.

Шаг 3. В соответствующих документах "ПлатежноеПоручениеИсходящее", "ПлатежныйОрдерСписаниеДенежныхСредств", "РасходныйКассовыйОрдер" - к имеющемуся типовому полю "Подразделение" была добавлена табличная часть "РаспределениеРасходовПоПодразделениям" с единственным полем "Подразделение" (см. рисунок).

Модель строится на следующем принципе:

- если расход денежных средств относится на конкретное подразделение, то соответствующее подразделение указывается только в типовом поле документа "Подразделение",

- если расход ДС необходимо распределить, то в типовом поле "Подразделение" необходимо выбрать подразделение "Администрация", а в табличной части "РаспределениеРасходовПоПодразделениям" указать все подразделения. Предполагается, что расходы относятся или только к одному подразделению, или сразу ко всем.

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

Самое сложное

- понять типовые алгоритмы и куда внести изменения с минимальными "потерями"

Шаг 4. В модуле объекта каждого документа проведение доработано следующим образом - в процедуру общего модуля передается массив подразделений:

Процедура ДвиженияПоРегистрамУпр(Режим, Отказ, Заголовок, СтруктураШапкиДокумента)

    ...
      
    УправлениеДенежнымиСредствами.ПровестиСписаниеДенежныхСредствУпр(
       
СтруктураШапкиДокумента, мСтруктураПараметровДенежныхСредств, ТаблицаПлатежейУпр,
       
Движения, Отказ, Заголовок, РаспределениеРасходовПоПодразделениям.ВыгрузитьКолонку("Подразделение")); //доработка+

КонецПроцедуры // ДвиженияПоРегистрамУпр()

 

В соответствующей процедуре общего модуля были внесены следующие правки:

Если Оплачено И (ОтраженоВОперУчете ИЛИ ПоРасчетномуДокументу) Тогда 

        // Проводим по фактическим взаиморасчетам

        // По регистру "Движения денежных средств"

       
ТаблицаДвиженияДенежныхСредств = Движения.ДвиженияДенежныхСредств.ВыгрузитьКолонки();

        ... // здесь код не менялся

        // Недостающие поля.
       
ТаблицаДвиженияДенежныхСредств.ЗаполнитьЗначения(ВидДенежныхСредств, "ВидДенежныхСредств");      

        ... // здесь код не менялся

        //доработка+ начало
       
Если МассивПодразделений <> Неопределено И МассивПодразделений.Количество()>0 Тогда

           
СоответствиеТаблиц = Новый Соответствие;
            Для
кол = 1 По МассивПодразделений.Количество() Цикл

                Если
кол = 1 Тогда

                   
СоответствиеТаблиц.Вставить(МассивПодразделений.Получить(кол-1), ТаблицаДвиженияДенежныхСредств);
                    Продолжить;

                КонецЕсли;

               
СоответствиеТаблиц.Вставить(МассивПодразделений.Получить(кол-1), ТаблицаДвиженияДенежныхСредств.Скопировать());

            КонецЦикла;
          

            ТаблицаДолей = МодульДоработок.ПолучитьТаблицуДолей(Дата, МассивПодразделений);       

           
времТаблицаДвиженияДенежныхСредств = ТаблицаДвиженияДенежныхСредств.СкопироватьКолонки();
            Для Каждого
Эл Из МассивПодразделений Цикл

               
ТЗ = СоответствиеТаблиц.Получить(Эл);
                Для Каждого
Стр Из ТЗ Цикл

                   
НоваяСтрока = времТаблицаДвиженияДенежныхСредств.Добавить();
                   
ЗаполнитьЗначенияСвойств(НоваяСтрока, Стр);
                   
НоваяСтрока.Проект      = Эл;
                  

                    //расходы распределяются пропорционально продажам за месяц
                   
СтрокаДолей = ТаблицаДолей.Найти(Эл, "Подразделение");

                   
НоваяСтрока.Сумма       = Стр.Сумма * СтрокаДолей.Доля;
                   
НоваяСтрока.СуммаУпр    = Стр.СуммаУпр * СтрокаДолей.Доля;                

                КонецЦикла;

            КонецЦикла;

           
//что было
            //Движения.ДвиженияДенежныхСредств.мПериод          = ДатаДвижений;
            //Движения.ДвиженияДенежныхСредств.мТаблицаДвижений = ТаблицаДвиженияДенежныхСредств;
            //Движения.ДвиженияДенежныхСредств.ВыполнитьДвижения();

            //что стало
           
Движения.ДвиженияДенежныхСредств.мПериод          = ДатаДвижений;
           
Движения.ДвиженияДенежныхСредств.мТаблицаДвижений = времТаблицаДвиженияДенежныхСредств;
           
Движения.ДвиженияДенежныхСредств.ВыполнитьДвижения();

        Иначе
           
//доработка+
           
ТаблицаДвиженияДенежныхСредств.ЗаполнитьЗначения(Ссылка.Подразделение, "Проект");

           
Движения.ДвиженияДенежныхСредств.мПериод          = ДатаДвижений;
           
Движения.ДвиженияДенежныхСредств.мТаблицаДвижений = ТаблицаДвиженияДенежныхСредств;
           
Движения.ДвиженияДенежныхСредств.ВыполнитьДвижения();

        КонецЕсли;
       
//доработка+ завершена

       ...
// здесь код не менялся

    КонецЕсли;

Самое интересное

- реализовать "соль" решения

Шаг 5. Таблица долей (коэффициентов) получается следующим образом:

Функция ПолучитьТаблицуДолей(ТекДата, СписокПодразделений) Экспорт

    Если Не
ЗначениеЗаполнено(ТекДата) Тогда
       
ТекДата = ТекущаяДата();
    КонецЕсли;

   
ТЗ = Новый ТаблицаЗначений;
   
ТЗ.Колонки.Добавить("Подразделение");
   
ТЗ.Колонки.Добавить("Доля");

   
Запрос = Новый Запрос;
   
Запрос.Текст = "ВЫБРАТЬ
    |   ПродажиОбороты.Подразделение,
    |   ПродажиОбороты.СтоимостьОборот КАК СтоимостьОборот
    |ИЗ
    |   РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , Подразделение В (&СписокПодразделений)) КАК ПродажиОбороты
    |
    |УПОРЯДОЧИТЬ ПО
    |   СтоимостьОборот УБЫВ
    |АВТОУПОРЯДОЧИВАНИЕ
"
;

   
Запрос.УстановитьПараметр("СписокПодразделений", СписокПодразделений);
   
Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекДата));
   
Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекДата));

   
ОбщиеПродажиЗаМесяц = МодульДоработок.ПолучитьОбщиеПродажиЗаМесяц(ТекДата, СписокПодразделений);

   
К = 1;
   
СуммаДолей = 0;

   
Выборка = Запрос.Выполнить().Выбрать();
    Пока
Выборка.Следующий() Цикл

        Если
К = СписокПодразделений.Количество() Тогда
           
Доля = 1 - СуммаДолей;
        Иначе
           
ПродажиЗаМесяц = Выборка.СтоимостьОборот;
           
Доля = Окр(ПродажиЗаМесяц/ОбщиеПродажиЗаМесяц,7);
           
СуммаДолей = СуммаДолей + Доля;
        КонецЕсли;

       
Стр = ТЗ.Добавить();
       
Стр.Подразделение = Выборка.Подразделение;
       
Стр.Доля = Доля;

    КонецЦикла;

    Возврат
ТЗ;

КонецФункции

 

В данной модели реализован расчет долей с учетом так называемой "проблемы копеек". Первые три по сумме продаж  магазина (подразделения) получают долю делением ПродажЗаМесяц на ОбщиеПродажиЗаМесяц, четвертый магазин получает долю = 1-СуммаДолей. Реализовано упорядочивание по суммам продаж по подразделениям.

Округления долей производится до 7 знака после запятой - что позволит избежать расхождений при умножении на семизначные суммы расходов.

Самое заключительное

- довести механизм до конечных показателей и отчетов

Шаг 6. Распределение административных расходов по подразделениям проводится в момент проведения документа. В конце месяца необходимо запустить групповое перепроведение документов. Для этого разработана обработка группового проведения документов - "Перепроведение документов за месяц" - перепроводятся только документы по административным расходам и имеющие заполненную таблицу "Распределение по подразделениям". В групповом перепроведении участвуют только документы вида ПлатежноеПоручениеИсходящее, ПлатежныйОрдерСписаниеДенежныхСредств, РасходныйКассовыйОрдер.

Шаг 7. Отчет по движению денежных средств строится по группировкам "Проект", "Статья движения денежных средств", остальные настройки - опционально при необходимости - "Вид денежных средств" (наличные, безналичные) , "Приход, расход".

Представленный механизм был реализован на платформе 8.3.11.3034 на конфигурации версии УТ 10.3.36.1.

С пользой для клиентов, RustIG (Rustем Iльдарович Gумеров)

6

См. также

Комментарии
Избранное Подписка Сортировка: Древо
1. tomvlad 3532 14.05.18 07:28 Сейчас в теме
А что, сейчас уже можно ссылку на свой сайт давать?
2. Rustig 1002 15.05.18 11:11 Сейчас в теме
3. tomvlad 3532 15.05.18 11:22 Сейчас в теме
(2) Раньше за такое Доржи бил линейкой по голове обещал строго наказать.
4. Rustig 1002 15.05.18 11:56 Сейчас в теме
(3) видимо, это было до внедрения модерации каждой статьи - сейчас модераторы не допускают статьи к публикации, если есть замечания
5. Rustig 1002 04.07.18 09:34 Сейчас в теме
(1) оказалось, что нельзя :)
удалил ссылку :(
6. strange2007 131 14.08.18 04:27 Сейчас в теме
Идея хорошая, но реализация сомнительная. Влазить в стандартную конфу как минимум не совсем разумно. Тем более если можно всё сделать в виде внешних идей. Оно и дешевле и более изолировано от других частей. Но это личное мнение, а не вселенская истина.
Недавно, например, делали распределение денег в ЗУПе тройке, в разрезе территорий (нет в стандартной нормального разделения, особенно если люди между территориями перемещаются по 10 раз в месяц). Две формочки, 2 настроечных регистра и всё. Конфу обновляю без проблем и финансовые гиганты пользуются достоверными цифрами.
7. Rustig 1002 14.08.18 09:30 Сейчас в теме
(6) все верно - согласен. если получается отделить ваш показатель задачи от типового расчета, то применяем свои регистры и алгоритмы в формочках. если не получается, то желательно адаптировать с минимальными потерями. я адаптировал минимально - обновление можно делать достаточно быстро - типовой код мало перемешан с моими доработками.
Одна из фищек моего решения - в технологии доработки - мне нравится что весь типовой код написан "блоками":
 //что было
            //Движения.ДвиженияДенежныхСредств.мПериод          = ДатаДвижений;
            //Движения.ДвиженияДенежныхСредств.мТаблицаДвижений = ТаблицаДвиженияДенежныхСредств;
            //Движения.ДвиженияДенежныхСредств.ВыполнитьДвижения();

            //что стало
            Движения.ДвиженияДенежныхСредств.мПериод          = ДатаДвижений;
            Движения.ДвиженияДенежныхСредств.мТаблицаДвижений = времТаблицаДвиженияДенежныхСредств;
            Движения.ДвиженияДенежныхСредств.ВыполнитьДвижения();
Показать


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

что еще: есть такой журнал "Финансовый директор" - достаточно дорогой для приобретения - около 1000 р. Во всех номерах иллюстрируется работа с Эксель - насколько это отличный инструмент для финан. директора и аналитика. Какие там строятся громоздкие системы учета - просто ужас- и в журнале редко описываются технологии использования 1С, да и на ИС мало подобного... в общем, я хотел бы разрушить мнение ,что эксель это круто для финансового директора - 1с поинтереснее будет.
8. strange2007 131 14.08.18 09:47 Сейчас в теме
(7) Не подумайте, что я злостно критикую. Уверяю, любой метод хорош, если он приносит должный результат. Просто надо же немного пальцы погнуть (без зла).

По поводу екселя тоже аккуратно действуйте. Не забывайте, что ексель (равно как и кальк) очень гибкий инструмент для одного человека и в этом его преимущество перед учётными системами. Рекомендую ознакомиться с системой фин.планирования и бюджетирования Майкрософта. В ней как раз на самом нижнем уровне используют именно ексель. А вот выше уже начинаются учётные системы.
Из личного опыта могу сказать, что беда начинается как только ексель становится основополагающим во всём. Кстати, недавно в 1С перевёл екселевскую работу одного отдела и... у них почти не стало работы)))))
9. Rustig 1002 14.08.18 10:20 Сейчас в теме
(8)
Не подумайте, что я злостно критикую. Уверяю, любой метод хорош, если он приносит должный результат. Просто надо же немного пальцы погнуть (без зла).

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


(8)
ексель (равно как и кальк) очень гибкий инструмент для одного человека и в этом его преимущество перед учётными системами

я не против эксель - эксель нормальный инструмент. как у плотника - есть зубило. есть молоток - каждому инструменту свое применение. не понимаю, почему мне приходится банальные вещи писать?

(8)
беда начинается как только ексель становится основополагающим во всём

я описал свой опыт использования 1с, в ут - в уже готвой системе учета можно реализовать интересные управленческие идеи. Использование 1с в этом плане мало где описано. Для эксель-наработок выходит целый журнал, вокруг эксель создана индустрия - для финан.директоров - эксель продвигается и продается. Что-то подобного я не вижу в плане 1с.

(8)
недавно в 1С перевёл екселевскую работу одного отдела и

об этом и речь в статье и в моих комментариях - делитесь своими наработками - нам не нужно писать друг другу дифирамбы ни про 1с, ни про эксель - просто делитесь наработками - сухими цифрами и кодом.
Оставьте свое сообщение