gifts2017

Начисление процентов по займов за произвольный период, процентные ставки могут меняться

Опубликовал Фишман Вадим (vvf1973) в раздел Программирование - Практика программирования

Есть задача начисления процентов по займам за произвольный период, включая случаи кратного количества лет, т.е. в общем случае, когда обе даты начала и конца периода  лежат в разных годах. Займы могут выплачиваться частями. Кроме того, процентные ставки по договорам займа могут меняться в любой момент (день). Эта задача была сделана в платформе 7.7, но с помощью объектной модели запросов по бухгалтерским итогам и таблицы значений. Сейчас я сделал исключительно через механизм запросов.

Описание задачи:
Есть задача начисления процентов по займам за произвольный период, включая случаи кратного количества лет, т.е. в общем случае, когда обе даты начала и конца периода  лежат в разных годах. Займы могут выплачиваться частями. Кроме того, процентные ставки по договорам займа могут меняться в любой момент (день). Эта задача была сделана в платформе 7.7, но с помощью объектной модели запросов по бухгалтерским итогам и таблицы значений. Сейчас я сделал исключительно через механизм запросов.



	ВЫБРАТЬ
    РегистрБухгалтерииХозрасчетныйОстаткиИОбороты.Счет КАК Счет,
    РегистрБухгалтерииХозрасчетныйОстаткиИОбороты.Субконто1 КАК Контрагент,
    РегистрБухгалтерииХозрасчетныйОстаткиИОбороты.Субконто2 КАК Договор,
    РегистрБухгалтерииХозрасчетныйОстаткиИОбороты.СуммаКонечныйОстаток КАК СуммаЗайма,
    РегистрБухгалтерииХозрасчетныйОстаткиИОбороты.Период
ПОМЕСТИТЬ Врем1
ИЗ
    РегистрБухгалтерии.РегистрБухгалтерииХозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, День, ДвиженияИГраницыПериода, Счет = ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ВыданныеЗаймы), , ) КАК РегистрБухгалтерииХозрасчетныйОстаткиИОбороты
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ПроцентныеСтавкиПоЗаймам.Период,
    ПроцентныеСтавкиПоЗаймам.Договор,
    ПроцентныеСтавкиПоЗаймам.ПроцентнаяСтавка
ПОМЕСТИТЬ Врем2
ИЗ
    РегистрСведений.ПроцентныеСтавкиПоЗаймам КАК ПроцентныеСтавкиПоЗаймам
ГДЕ
    ПроцентныеСтавкиПоЗаймам.Период     И ПроцентныеСтавкиПоЗаймам.Период >= &НачалоПериода
    И ПроцентныеСтавкиПоЗаймам.Договор В
            (ВЫБРАТЬ РАЗЛИЧНЫЕ
                Врем1.Договор
            ИЗ
                Врем1 КАК Врем1)

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    ПроцентныеСтавкиПоЗаймамСрезПоследних.Период,
    ПроцентныеСтавкиПоЗаймамСрезПоследних.Договор,
    ПроцентныеСтавкиПоЗаймамСрезПоследних.ПроцентнаяСтавка
ИЗ
    РегистрСведений.ПроцентныеСтавкиПоЗаймам.СрезПоследних(
            &НачалоПериода,
            Договор В
                (ВЫБРАТЬ РАЗЛИЧНЫЕ
                    Врем1.Договор
                ИЗ
                    Врем1 КАК Врем1)) КАК ПроцентныеСтавкиПоЗаймамСрезПоследних
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Врем1.Счет,
    Врем1.Контрагент,
    Врем1.Договор,
    Врем2.Период,
    Врем1.СуммаЗайма,
    МАКСИМУМ(Врем1.Период) КАК Период1
ПОМЕСТИТЬ Врем3
ИЗ
    Врем1 КАК Врем1
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Врем2 КАК Врем2
        ПО Врем1.Договор = Врем2.Договор
            И Врем1.Период
СГРУППИРОВАТЬ ПО
    Врем1.Счет,
    Врем1.Контрагент,
    Врем1.Договор,
    Врем2.Период,
    Врем1.СуммаЗайма
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Врем1.Счет КАК Счет,
    Врем1.Контрагент КАК Контрагент,
    Врем1.Договор КАК Договор,
    ДОБАВИТЬКДАТЕ(КОНЕЦПЕРИОДА(Врем1.Период, ГОД), СЕКУНДА, 1) КАК Период,
    МАКСИМУМ(Врем1.Период) КАК Период1
ПОМЕСТИТЬ Врем4
ИЗ
    Врем1 КАК Врем1
ГДЕ
    ДОБАВИТЬКДАТЕ(КОНЕЦПЕРИОДА(Врем1.Период, ГОД), СЕКУНДА, 1)
СГРУППИРОВАТЬ ПО
    Врем1.Счет,
    Врем1.Контрагент,
    Врем1.Договор,
    ДОБАВИТЬКДАТЕ(КОНЕЦПЕРИОДА(Врем1.Период, ГОД), СЕКУНДА, 1)
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Врем4.Счет,
    Врем4.Контрагент,
    Врем4.Договор,
    Врем4.Период,
    Врем1.СуммаЗайма
ПОМЕСТИТЬ Врем5
ИЗ
    Врем1 КАК Врем1
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Врем4 КАК Врем4
        ПО Врем1.Счет = Врем4.Счет
            И Врем1.Контрагент = Врем4.Контрагент
            И Врем1.Период = Врем4.Период1
            И Врем1.Договор = Врем4.Договор
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Врем1.Счет КАК Счет,
    Врем1.Контрагент КАК Контрагент,
    Врем1.Договор КАК Договор,
    Врем1.Период КАК Период,
    Врем1.СуммаЗайма КАК СуммаЗайма
ПОМЕСТИТЬ Врем6
ИЗ
    Врем1 КАК Врем1

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    Врем3.Счет,
    Врем3.Контрагент,
    Врем3.Договор,
    Врем3.Период,
    Врем3.СуммаЗайма
ИЗ
    Врем3 КАК Врем3

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    Врем5.Счет,
    Врем5.Контрагент,
    Врем5.Договор,
    Врем5.Период,
    Врем5.СуммаЗайма
ИЗ
    Врем5 КАК Врем5
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Врем6.Счет,
    Врем6.Контрагент,
    Врем6.Договор,
    Врем6.Период,
    Врем6.СуммаЗайма,
    МАКСИМУМ(Врем2.Период) КАК Период1
ПОМЕСТИТЬ Врем7
ИЗ
    Врем6 КАК Врем6
        ЛЕВОЕ СОЕДИНЕНИЕ Врем2 КАК Врем2
        ПО Врем6.Договор = Врем2.Договор
            И Врем6.Период >= Врем2.Период

СГРУППИРОВАТЬ ПО
    Врем6.Счет,
    Врем6.Контрагент,
    Врем6.Договор,
    Врем6.Период,
    Врем6.СуммаЗайма
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Врем7.Счет,
    Врем7.Контрагент,
    Врем7.Договор,
    Врем7.Период,
    Врем7.СуммаЗайма,
    ЕСТЬNULL(Врем2.ПроцентнаяСтавка, 0) КАК ПроцентнаяСтавка
ПОМЕСТИТЬ Врем8
ИЗ
    Врем7 КАК Врем7
        ЛЕВОЕ СОЕДИНЕНИЕ Врем2 КАК Врем2
        ПО Врем7.Договор = Врем2.Договор
            И Врем7.Период1 = Врем2.Период
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Врем8.Период КАК НачалоПериода,
    МИНИМУМ(ЕСТЬNULL(ДОБАВИТЬКДАТЕ(Врем81.Период, СЕКУНДА, -1), &КонецПериода)) КАК КонецПериода,
    Врем8.Счет,
    Врем8.Контрагент,
    Врем8.Договор,
    Врем8.СуммаЗайма,
    Врем8.ПроцентнаяСтавка
ПОМЕСТИТЬ Врем9
ИЗ
    Врем8 КАК Врем8
        ЛЕВОЕ СОЕДИНЕНИЕ Врем8 КАК Врем81
        ПО Врем8.Счет = Врем81.Счет
            И Врем8.Контрагент = Врем81.Контрагент
            И Врем8.Договор = Врем81.Договор
            И Врем8.Период < Врем81.Период

СГРУППИРОВАТЬ ПО
    Врем8.Счет,
    Врем8.Договор,
    Врем8.Контрагент,
    Врем8.Период,
    Врем8.СуммаЗайма,
    Врем8.ПроцентнаяСтавка
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Врем9.НачалоПериода КАК НачалоПериода,
    Врем9.КонецПериода,
    Врем9.Счет КАК Счет,
    Врем9.Контрагент КАК Контрагент,
    Врем9.Договор КАК Договор,
    Врем9.СуммаЗайма,
    Врем9.ПроцентнаяСтавка,
    РАЗНОСТЬДАТ(Врем9.НачалоПериода, Врем9.КонецПериода, ДЕНЬ) + 1 КАК РазностьДат,
    РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Врем9.НачалоПериода, ГОД), КОНЕЦПЕРИОДА(Врем9.КонецПериода, ГОД), ДЕНЬ) + 1 КАК КоличествоДнейВГодах,
    ВЫРАЗИТЬ(Врем9.СуммаЗайма * Врем9.ПроцентнаяСтавка / 100 * (РАЗНОСТЬДАТ(Врем9.НачалоПериода, Врем9.КонецПериода, ДЕНЬ) + 1) / (РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Врем9.НачалоПериода, ГОД), КОНЕЦПЕРИОДА(Врем9.КонецПериода, ГОД), ДЕНЬ) + 1) * (ГОД(Врем9.КонецПериода) - ГОД(Врем9.НачалоПериода) + 1) КАК ЧИСЛО(15, 2)) КАК НачисленныйПроцент
ИЗ
    Врем9 КАК Врем9
ГДЕ
    Врем9.НачалоПериода <> Врем9.КонецПериода
    И Врем9.СуммаЗайма > 0

    
1.    В первом запросе мы производим выборку остатков по суммам займов на протяжении периода. При этом метод дополнения мы выбираем такой, чтобы получить остатки даже если не было движений по займам в течение периода.
2.    Во втором запросе мы делаем выборку процентных ставок, выбирая сначала существующие ставки на начало периода, а затем объединяя это выборку с изменениями процентных ставок в пределах периода. Каждая выборка ограничивается теми договорами, которые были выбраны на первом этапе.
3.    Изменение процентной ставки вызывает дробление периода расчета, т.е., например, если сумма займа постоянна на каком отрезке времени, то изменение процентной ставки внутри этого отрезка времени делит этот отрезок времени на две части, двукратное изменение внутри  этого отрезка на три части и т.д.. Поэтому мы делаем выборку тех дат изменения процентных ставок, которые внутри периода отчета и находим ближайшие к ним значения сумм займов, счетов, контрагентов.
4.    В четвертом запросе мы учитываем, что период отчета может быть лежать в разных годах, т.е., например, отрезок времени должен поделиться на такие отрезки: Дата1-КонецГода(Дата1), Начало следующего года-Дата2/Конец н-го года.
5.    К четвертому запросу добавляем, где мы получаем начала следующих годов, добавляем суммы займов.
6.    Объединяем все полученные данные.
7.    Запросы 7 и 8 позволяют вычислить недостающие значения процентных ставок.
8.    Запрос 9 формирует периоды для расчетов.
9.    Последний запрос вычисляет суммы процентов. Оператор Выразить используется для округления.
Если интервал представляет собой кратное количество лет, то умножается на количество лет, если нет, то на 1.

Прилагается выгрузка с тестовыми примерами, отчет сделанный с помощью СКД "Отчет по начисленным процентам", призванные показать алгоритм.

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
Выгрузка конфигурации
.dt 38,70Kb
10.07.14
50
.dt 38,70Kb 50 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Vladimir (Boroda) 26.12.11 22:54
Как я понимаю, это будет работать в Бухгалтерии лишь? Или для ЗУП тоже подойдёт?
2. Igоr Sаulеviсh (gutentag) 27.12.11 02:07
(1) Ну вряд ли, работодатели или главбухи захотят в ЗУПе давать/оформлять займы с "плавающими ставками" и мыкаться с расчетом мат.выгоды.
Но чисто теоретически, вопрос поставлен верно :)
3. Igоr Sаulеviсh (gutentag) 27.12.11 02:09
(1)
ВЫБРАТЬ
РегистрБухгалтерииХозрасчетныйОстаткиИОбороты.Счет КАК Счет,


имхо судя по этой строке, без доработки напильником в ЗУПе врядли заработает...................................................................................
4. Фишман Вадим (vvf1973) 27.12.11 08:07
(1)
Историю хранения остатков по выданным займам или полученным вы можете хранить/получать как сочтете нужным, т.е. Вам любым удобным способом надо получить историю остатков, где указываются вид займа(выданный, полученный), разрезы учета займа(договор и контрагент/сотрудник, может еще какие-то разрезы), дата изменения займа, сумма займа. Метод, указанный в статье, имхо, по сути универсален.
5. Vladimir (Boroda) 27.12.11 21:49
(1) Вот как раз столкнулся с необходимостью ведения подобного начисления и уплаты займов в зарплате. Дело в том, что при займе должна также расчитываться мат.выгода и НДФЛ с неё, а это удобнее делать в зарплатных программах для того, чтобы годовой отчёт по НДФЛ формировался автоматически. Ну, а поскольку в обычных организациях (ну, в очень простых, где сотрудникам платится лишь оклад да премия, болеть нельзя и т.п. - можно зарплату считать и в Бухгалтерии) НДФЛ считается в ЗУП (ЗиК), то целесообразно и займ считать в них. Но стандартный займ и расчёт его погашения очень "жёсткий", и не всегда удобен, особенно, когда сотр склонен платить нерегулярно, а подобный расчёт как раз отличается гибкостью.
(4) Спасибо, я понял, что можно попробовать использовать применительно к ЗУП сам метод, а обработка под Бухгалтерию.
6. Igоr Sаulеviсh (gutentag) 28.12.11 10:24
(5) если получится, то поделитесь, пжст, результатом - очень надо для ЗУП-8
-----------------------------------------------------------------------------------------------------------------

(4) т.к. я бухгалтер, а не программер, то я никогда не понимал и не понимаю: зачем надо вносить изменеия в конфигураторе, если можно сделать все в обработке, а дополнительные сведения и регистры хранить во внешнем/их файлах(формат файла по-вкусу). Тем более что расчет процентов по займам/кредитам = имхо делается раз в месяц(но в любом случае быстродействие системы/конфигурации бухгалтеру для такой операции тут не потребуется). ИМХО.

ставлю плюс только за решение посталенной задачи/идеи
7. Светлана (sps02) 21.07.14 16:59
Здравствуйте. По скрину видно что только в 1С 8.3 работает??Верно?
8. Фишман Вадим (vvf1973) 24.07.14 16:55
(7)
Управляемые формы работают и на 8.2. Сам алгоритм - это запрос и не зависит от режима (обычные или управляемые формы)
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа