gifts2017

Расчет банковских (рабочих) дней (Оригинальный способ)

Опубликовал г. Казань Рустем Гумеров (Rustig) в раздел Отчеты - Бухгалтерские

Как я рассчитал количество банковских дней в конфигурации, в которой, как мне казалось, нет производственного календаря - в конфигурации "Бухгалтерия предприятия 2.0".
Метод применим для совершенно любой конфигурации: в том числе для ЗУП, в которой имеется соответствующий календарь.
(Позже из комментариев выяснилось, что календарь-таки есть.)

Началось все с того, что понадобилось рассчитать просроченную задолженность покупателей с учетом отсрочки платежа в 10-ть банковских дней. Задача ставится на конфигурации "Бухгалтерия предприятия 2.0". Задачу расчета просрочек я решил в короткие сроки благодаря Инфостарту. Оставалось только учесть банковские дни просрочек, а не календарные.

Я решил так, что банковские дни - это по сути то же самое, что и рабочие дни при пятидневке в производственном календаре. Производственный календарь я взял из конфигурации ЗУП. На рисунке 1 показан взятый из пользовательского режима график работы и сохраненный в табличный документ mxl (рис.1).

рис.1 График работы 2014 г

рис. 1. График работы в 2015 г, пятидневка, конфигурация ЗУП

Вторым шагом я сохранил данный календарь в формате таблиц 1С - *.mxl. Удалил лишние строки и колонки. Скопировал получившийся календарь в макет обработки (рис.2).

рис.2 Макет календаря в обработке

рис.2. Макет календаря в обработке

В результате макет календаря стал выглядеть так: в строках заданы месяцы, в колонках - дни (рис.3).

рис.3. Календарь: месяцы - это строки, дни - это колонки

рис.3. "Подготовленный формат" календаря: месяцы - это строки, дни - это колонки

В модуле обработки я создал функции: первая возвращает количество банковских (рабочих) дней в заданном периоде, вторая - проверяет, является ли заданный день банковским, третья - прибавляет заданное количество банковских дней к заданной дате. 

Функция ПолучитьКолБанкДней(ДатаНачала, ДатаОкончания) Экспорт

   
ОчереднойДень = НачалоДня(ДатаНачала);
   
КолБанкДней = 0;
    Пока
ОчереднойДень<=НачалоДня(ДатаОкончания) Цикл

       
Макет = ПолучитьМакет("Год" + Формат(Год(ОчереднойДень), "ЧГ=0"));
       
стр = Месяц(ОчереднойДень);
       
кол = День(ОчереднойДень);
       
Текст = Макет.Область(стр, кол, стр, кол).Текст;
       
КолБанкДней = КолБанкДней + ?(Текст = "8", 1, 0);

       
ОчереднойДень = ОчереднойДень + 24*3600;
    КонецЦикла;

   
Сообщить(КолБанкДней);

    Возврат
КолБанкДней;

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

Функция
ПрибавитьКолБанкДней(НачальнаяДата, КолБанкДней) Экспорт

   
КонечнаяДата = НачальнаяДата;
    Пока
КолБанкДней>0 Цикл
       
КонечнаяДата = КонечнаяДата + 24*3600;
        Если
ЭтоБанковскийДень(КонечнаяДата) = Истина Тогда
           
КолБанкДней = КолБанкДней - 1;
        КонецЕсли;
    КонецЦикла;

    Возврат
КонечнаяДата;

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

Функция
ЭтоБанковскийДень(ОчереднойДень) Экспорт

   
Макет = ПолучитьМакет("Год" + Формат(Год(ОчереднойДень), "ЧГ=0"));
   
стр = Месяц(ОчереднойДень);
   
кол = День(ОчереднойДень);
   
Текст = Макет.Область(стр, кол, стр, кол).Текст;
    Возврат ?(
Текст = "8", Истина, Ложь);

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

К статье прикреплена обработка "Производственный календарь.epf", содержащая календари банковских (рабочих) дней в макетах за 2010-2015 год и вышеуказанные функции для тестирования.

Всем всего доброго и успехов в работе!

Центр автоматизации, г. Казань http://go-scan.ru/

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

Наименование Файл Версия Размер
Обработка ПроизводственныйКалендарь 3
.epf 17,70Kb
26.03.15
3
.epf 17,70Kb Скачать

См. также

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

Комментарии

1. Римма Герасименко (WhiteOwl) 25.03.15 10:33
2. Василий Коровин (vasyak319) 25.03.15 10:41
Жесткач. Хорошо, что современные машины делают по несколько миллиардов операций в секунду и их не убить даже такими алгоритмами.
3. Игорь Пашутин (Alien_job) 25.03.15 11:02
(2) vasyak319, да ладно - регламентные отчеты тоже свои настройки в макетах хранят. Хотя в циклах они их, конечно, не получают.
4. Василий Коровин (vasyak319) 25.03.15 11:34
(3) Alien_job,
Хотя в циклах они их, конечно, не получают

во-во. Кроме того, из тех настроек слова не выкинешь, там всё нужно, а тут целая простыня ради нескольких чисел, хотя всё, что необходимо для этого алгоритма, это список отклонений, т.е. субботы-воскресенья, которые считаются банковскими днями и остальные дни недели, которые такими не считаются, а таких отклонений в год десяток.
Плюс отдельная премия Дарвина за вычисление перебором дней (особенно клёво, когда начальная дата пустая - тогда это over 700 тыщ итераций), что, впрочем, вытекает из остальных косяков алгоритма.
корум; +1 Ответить 3
5. Евгений Аганин (AganinEvgeniy) 25.03.15 11:56
Идея и правда не плоха ... но согласен с Василием, легче выбирать 20 отклонений в год и плюсовать их к номеру дня недели или что-то подобное намудрить, чем перебором обходить 365 дней.
6. fzt fzt (fzt) 25.03.15 12:03
А почему бы и нет. Идея довольно простая и конфа не снята с поддержки.
Как улучшить:
1) Формируем всю эту радость в екселе.
2) К xls файлам можно делать полноценные SQL запросы, через драйвер ODBC (в поставке любой винды).
Экономия кучи машинного времени.
7. г. Казань Рустем Гумеров (Rustig) 25.03.15 12:54
(4) задача решается на файловой базе, период расчета неустойки три года: с начала 2013г по текущий день 2015 г включительно - летает "на ура!" - проблем с производительностью нет. по поводу мелких недочетов - тут каждый сам решает для себя - у меня дата начала не может быть пустой - изначально стоит проверка в другой процедуре. такие дела. за замечания спасибо: может быть другим пригодится.
8. г. Казань Рустем Гумеров (Rustig) 25.03.15 13:21
(4) ваше замечание заставило меня задуматься: почему же при таком алгоритме проблем с производительностью не возникает? Оказывается, это следует из специфики самой постановки задачи - расчета просрочек: условно говоря, просрочка считается от ДатыОтгрузки до ДатыСледующегоСобытия (или даты оплаты или даты следующей отгрузки). Таким образом для каждой реализации (отгрузки) возникшая пара "ДатаНачала"-"ДатаОкончания" является "коротким" периодом, то есть к примеру от 14.03.2014 до 23.03.2014 прошло 9 календарных дней - в этом периоде определяется 6 банковских дней. То есть по сути цикл в алгоритме состоит из 9 итераций - проверяем каждый день является ли он банковским. Еще раз спасибо за замечание!
9. г. Казань Рустем Гумеров (Rustig) 25.03.15 13:50
(4) для более сложных задач (многоитерационных алгоритмов) можно при открытии формы обработки формировать временную таблицу значений, вытаскивая сведения из макета, а потом использовать эту таблицу в запросах.
10. Василий Коровин (vasyak319) 25.03.15 14:26
(8) Rustig, просто у вас объём маленький, а современные машины сцуко быстрые, так что если алгоритм, который при нормальной реализации отработал бы за микросекунду, работает в тысячу раз медленнее, вы этого один чёрт не заметите. Но это всё равно плохо, потому что миллисекунда тут, миллисекунда там, а в итоге документы по полминуты проводятся.
И это не просто теория, мне постоянно приходится давать ускоряющего пинка кривым алгоритмам, которые на полупустых базах летали.
Кроме того, это сейчас ваша процедура используется исключительно для отсрочки 10 дней. Другая задача появится, где тоже нужны будут банковские дни, и вы её либо заново переписывать будете, либо она будет у вас тормозить.
11. Василий Коровин (vasyak319) 25.03.15 14:43
(9) Rustig, т.е. передавать весь массив данных серверу - пусть развлекается? Снова неоправданная жестокость. На самом деле, если у вас всё ограничено известным периодом (а у вас всё как минимум ограничено периодом, для которого у вас есть календари), то вычисление каждой отсрочки можно свести к разности двух элементов одного массива.
12. г. Казань Рустем Гумеров (Rustig) 26.03.15 07:13
(11) мне кажется не стоит сгущать тучи по поводу производительности, предлагаю решать проблемы по мере их поступления, а не прогнозировать плохую производительность в будущих задачах и предлагаю не смешивать с этой задачей проблему долгого проведения документов - совсем уж разные темы.
Тема этой статьи - заключается в том, в БП 2.0 надо было посчитать банковские дни. Я описал одну из возможных реализаций. На мой скромный взгляд, получилось оригинально. :)
13. Василий Коровин (vasyak319) 26.03.15 11:31
(12) Rustig, кстати, вот мне это сразу показалось странным, но я вам поверил, что в БП 2.0 нет производственного календаря. Сейчас решил таки посмотреть - он там есть. Тогда зачем вообще это всё?
tano23; Alien_job; +2 Ответить 2
14. г. Казань Рустем Гумеров (Rustig) 26.03.15 14:23
(13) что за объект метаданных?
15. г. Казань Рустем Гумеров (Rustig) 26.03.15 14:26
(13), (14) есть такой - регистр сведений Регламентированный производственный календарь. Ну, отлично! что ж сказать? не знал, что такой есть.
16. Dmitry Bas (b-dm) 27.03.15 11:28
А все равно публикация классная. Мне нпонравилось и решение и описание. Плюс.
17. Димон * (DDos76) 31.03.15 19:37
Реально способ оригинальный. За способ поставил +!
Следующий этап - календарь будет храниться в экселе, сначала по OLE (Пардон COM) попробуем оттуда забирать.
К xls файлам можно делать полноценные SQL запросы, через драйвер ODBC (в поставке любой винды). - это не так интересно.
Если будет медленно - там и до PegExp рукой подать. Разбор файла .XLS средствами 1с так сказать.
С 1 Апреля!
dgolovanov; +1 Ответить
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа