Расширение "Двойная запись"
Расширение "Двойная запись" - это экспериментальное приложение, предназначенное для обработки учётных данных, представленных в формате двойной бухгалтерской записи. Исследуемые объекты идентифицируются счетами, на каждом из которых ведётся учёт в стоимостном и натуральном выражении. Движение объектов описывается проводками перемещения стоимостных и натуральных значений в выбранных измерителях с кредита одного в дебет другого счёта. Блоки проводок по счетам группируются в рамках произвольно выбранных пользователем меток времени. Проводки по счетам могут маркироваться произвольным набором меток, которые в последующем могут использоваться для построения выборок данных в нужных пользователю разрезах. Движения по счетам могут обобщаться с помощью совокупности стандартных отчётов, а также встраиваться в произвольные тексты статей как отдельные фразы. Каждый счёт может иметь произвольный набор атрибутов для использования последних в специализированных вычислениях, которые могут произвольно создаваться пользователями по определённым правилам с использованием либо встроенного языка программирования системы, либо общеизвестного языка программирования PHP. Счета могут входить в произвольное число групп, а значения оборотов и остатков нескольких счетов могут агрегироваться в произвольные наборы агрегирующих счетов, что обеспечивает возможность обобщения данных практически в любых разрезах.
Использование расширения требует наличия файлов x_dz.api, x_dz.php, x_dz.txt, x_dzs.php, x_dzsa.php, которые не входят в базовую комплектацию.
Назначение расширения
Расширение "Двойная запись" может использоваться для ведения учёта движения практических любых сущностей. Например, автор использует его для учёта определённой части приходов денежных средств и части повседневных покупок, а также помесячного учёта продаж изданных им книг в разрезе их наименований и продавцов.
За счёт использования возможностей агрегирования данных первичных счетов в агрегирующие счета, в принципе, возможно и ведение упрощённого бухгалтерского учёта небольшого предприятия. При этом за счёт средств специализированных расчётов, как обобщения понятия "Типовая операция", можно выстроить практически любые модели автоматизации типовых и специфических для конкретного пользователя бухгалтерских вычислений. Примеры реализации подобных вычислений рассматриваются далее. Однако данное расширение вряд ли пригодно для ведения оперативного и бухгалтерского учёта в "промышленных" масштабах - для этого есть хорошо апробированные специализированные программы. В то же время, расширение может быть полезно для некоторого обобщённого анализа последствий осуществления совокупностей хозяйственных операций. Например, для выявления потенциальных угроз возникновения ситуаций технической неплатёжеспособности.
Концепция построения расширения и технологии его функционирования является свободной фантазией автора на темы популярных в прошлом программ "Турбо-бухгалтер" и "Финансы без проблем". Из первых версий "Турбо-бухгалтера" позаимствована концепция интерфейса ввода исходных данных с помощью обычного текстового редактора, а из "Финансов без проблем" - идея полного пересчёта итоговых данных "от потопа", без хранения каких-либо промежуточных результатов на долгосрочных носителях, а также механизм параметров счетов, которые могут хранить произвольную вспомогательную информацию, используемую специализированными алгоритмами.
Исходные данные расширения
Исходными данными расширения "Двойная запись" являются два текстовых файла:
файл описания счетов (ФОС);
файл массива проводок (ФМП).
В общем случае обязательным является только ФМП. ФОС используется исключительно для оформления отчётов, агрегирования данных, а также для выполнения специализированных расчётов.
Каждый из указанных файлов может включать произвольное число команд вставки данных (^) из других источников (см. Вставка данных из других источников ). Таким образом, ФОС и ФМП могут формироваться из неограниченного числа сторонних файлов и их секций.
Порядок формирования строк ФОС и ФМП рассматривается далее. Помимо "значащих" строк, определённых по заданным правилам, в них может включаться произвольное число пустых строк и строк комментариев, начинающихся с символов и *.
Основные понятия расширения
Основными понятиями системы являются:
первичные счета;
атрибуты счетов;
проводки по счетам;
блоки проводок;
метки проводок;
отчёты;
расшифровки реквизитов отчётов;
группы счетов;
агрегирующие счета;
независимые встроенные функции вычисления итогов;
функции и модули выполнения специализированных расчётов пользователей.
Первичные счета
Первичный счёт - это произвольная комбинация символов, идентифицирующих некоторую неделимую сущность, движение которой учитывается в стоимостных и натуральных измерителях.
Например, первичный счёт Морковь может учитывать покупки моркови в магазинах с рублях и килограммах. И то и другое всегда есть в чеке. Первичный счёт Литрес может учитывать продажу книг через продавца Литрес (в рублях и штуках, независимо какая книга). Первичный счёт ПивоКрепкое может учитывать все покупки крепкого пива, независимо от его марки (в рублях и литрах).
Первичный счёт ВТБ может учитывать приходы на карты, открытые в банке ВТБ, а также покупки, оплаченные с использованием этих карт. В данном случае учёт в натуральных измерителях смысла не имеет. Однако программы расширения автоматически ведут учёт на каждом счёте и по стоимости и в натуре. Фактически, в этом случае натуральное измерение суммирует "бочки с селёдками". Например, оплаченные с этих карт килограммы моркови и литры пива. С помощью специального атрибута счёта можно запретить вывод в отчётах по такому счёту натуральных данных и оставить только стоимостное измерение.
Выбор первичных счетов и их детализация зависит от решаемой пользователем задачи. Но с точки зрения программ расширения первичный счёт - это некоторая неделимая сущность. При кодировании первичных счетов можно использовать любые символы, кроме символов пробел и точка (.), имеющие специальное назначение. Однако, возможно, в дальнейшем некоторые символы будут каким-то образом специально интерпретироваться. В особенности это касается спецсимволов, с помощью которых может быть введена особая интерпретация частей кода первичного счёта. Поэтому для именования счетов настоятельно рекомендуется использовать только буквенно-цифровые обозначения, а также символ подчёркивания (_).
В запросах на формирование отчётов или выполнение определённых вычислений может использоваться маска счёта - первые символы совпадающие у нескольких первичных счетов. В этом случае программы расширения будут интерпретировать все счета проводок, начинающиеся с одной и той маски как один счёт. Например, если в проводках используются счета с кодами ПивоКрепкое и ПивоЛегкое, а в запросе указана маска Пиво, то стоимостные и натуральные данные указанных счетов будут объединены. То есть в рассмотрение попадут проводки по счетам ПивоКрепкое и ПивоЛегкое.
Атрибуты счетов
Атрибуты счетов могут включать произвольную информацию каким-то образом характеризующую те или иные свойства счёта. В ФОС атрибут счёта должен отделяться от кода счёта символом точка (.). Атрибуты делятся на предопределённые и произвольные. Предопределённые атрибуты имеют код состоящий из единственной латинской буквы. Произвольные атрибуты могут иметь любое алфавитно-цифровое обозначение, состоящее не менее, чем из двух символов. Например в ФОС заданы следующие определения:
Бананы.n Бананы
Бананы.g Еда
Бананы.k 1
Бананы.aps1 Еда
Бананы.aps2 Фрукты
Билайн.n Платежи за мобильную связь и Интернет
Билайн.g Связь
Билайн.k 0
Билайн.aps1 Связь
Билайн.aps2
В данном примере для каждого из приведённых счетов указано по 5 атрибутов. Атрибуты n,g,k - предопределённые. Их программы расширения будут использовать по вполне конкретным правилам. Атрибуты aps1, aps2 - произвольные. Их обработка зависит от контекста использования в запросах на выполнение тех или иных действий.
На настоящий момент предопределены всего 3 атрибута:
n - название счёта, которое выводится в отчётах;
g - перечень групп счетов, в которые входит данный счёт (используется для выборок);
k - признак необходимости вывода в отчётах натуральных данных (не ноль - выводятся, 0 - не выводятся, по умолчанию - 1).
В произвольных параметрах счёта можно задать агрегирующий счёт для данного первичного, норму амортизации, дневной тариф оплаты труда и т.д., которые будут использованы в специальных расчётах. Имеются возможности динамически переопределять значение произвольного атрибута. Например, до одной даты атрибут счёта имеет одно значение, а после неё - другое.
Проводки по счетам
Проводки по счетам отражают перемещение средств в стоимостном и натуральном выражении с одного счёта (дебетуемого) на другой (кредитуемый). На кредитуемом счёте убывает, на дебетуемом - прибывает. Тут нет практически никаких отличий от традиционного бухгалтерского трактования. Поэтому и запись проводок по счетам практически полностью повторяет записи, в большом числе присутствующие в любом учебнике по бухучёту. Отличия только в том, что кроме суммы проводки в стоимостном выражении может указываться ещё значение в натуральном выражении.
Например, в ФМП указаны следующие строки:
ВТБ Пенсия 30221.27
Матрас ТБанк 8831.00 1
КлавМышь ТБанк 1497.00 1
Кабель ТБанк 204.00 1
ПивоКрепкое ВТБ 124.99 1.2
ХлебЧер ВТБ 35.99 0.35
Чай ВТБ 152.99 0.2
Редька ВТБ 64.79 0.96
Курица ВТБ 278.73 1.566
Чеснок ВТБ 160.06 0.39
Курево ВТБ 155.00 1
Здесь в каждой проводке 3 или 4 слова - комбинаций символов, разделённых пробелами. Первое слово - код дебетуемого счёта, второе - код кредитуемого счёта, третье - сумма проводки в стоимостном выражении. Эти три слова являются обязательными. Если задано четвёртое слово, то оно интерпретируется как сумма проводки в натуральном выражении. Единица измерения пока никак не оговаривается. Предполагается, что для каждого счёта она своя и единая для всех проводок с участием данного счёта.
В представленном примере проводка:
ВТБ Пенсия 30221.27
означает, что на счёт ВТБ со счёта Пенсия поступила сумма 30221.27.
Проводка:
Курица ВТБ 278.73 1.566
характеризует дебетование счёта Курица (покупка курицы) и кредитование счёта ВТБ (оплата картой) на сумму 278.73. При этом на счёт Курица поступило 1.566 единиц в натуральном выражении. В человеческой интерпретации это означает, что куплена курица весом 1.566 кг., на сумму 278.73 руб. Оплата произведена картой банка ВТБ. Всё довольно прозрачно.
Суммы проводки (стоимостные и натуральные) не обязательно могут быть числами. Для проводок, являющихся объектом специальной обработки это могут быть ссылки на программы вычислений.
Например:
Стройка Доска $ssc 100
Здесь $ssc - это ссылка на модуль программы на встроенном языке, который будет вызван для расчёта списания по средней цене 100 учётных единиц со счёта Доска в дебет счёта Стройка. Модуль рассчитает по предыдущим проводкам средневзвешенную цену единицы натурального учёта на счёте Доска, умножит её на 100 (число списываемых единиц) и подставит вместо $ssc. Подробнее эта возможность разбирается далее.
Помимо перечисленных параметров, проводка может включать также автоматически или вручную сопоставленные им метки (рассматриваются далее).
Блоки проводок
Проводки делятся на блоки, характеризуемые метками времени, используемыми для различных выборок для отчётов и/или специальных вычислений.
Метка времени - это произвольная комбинация символов, позволяющая установить последовательность обработки проводок.
Метка задаётся отдельной строкой ФМП, начинающейся после символа #.
Главное требование к меткам времени состоит в том, чтобы они могли быть выстроены по возрастанию при сортировке. За счёт меток времени устанавливается логическая последовательность блоков проводок. Поэтому детализация времени может любой: по годам, месяцам, дням, часам, минутам, секундам и даже подробнее.
Например, при учёте продаж книг статистика выдаётся продавцами по месяцам. Поэтому в соответствующем ФМП метки времени соответствуют конкретному месяцу. Поэтому может быть введено кодирование: ГГГГ-ММ.
Например:
#2024-10
ИЭ ЛитРес 50 1
ИЭ Yandex_Bookmate 3.65 2.9
ТССА ЛитРес 150 3
ТССА Yandex_Bookmate 99.64 43.46
ЭАПВ Yandex_Bookmate 12.73 4.59
ЭАПВ МТС_Строки 0.38 3
ФА Yandex_Bookmate 13.85 10.67
ФА МТС_Строки 22.58 1
МРПС Yandex_Bookmate 0.46 0.57
Пихто Yandex_Bookmate 0.12 0.03
ЛМНИ Yandex_Bookmate 7.93 3.46
КЗЭП Yandex_Bookmate 0.64 0.18
Манифест Партнеры_ЛитРес 0.04 2
ИИБД Yandex_Bookmate 10.53 12.42
БД AMAZON 50 1
БД Yandex_Bookmate 125.49 78.62
#2024-11
ИЭ ЛитРес 50 1
ТССА ЛитРес 200 4
ТССА OZON 200 4
ТССА Yandex_Bookmate 135.24 69.75
ТССА МТС_Строки 94.89 1
ЭАПВ Yandex_Bookmate 6.92 2.95
ЭАПВ МТС_Строки 45.93 4
ФА Yandex_Bookmate 3.45 3.14
ФА МТС_Строки 33.4 4
ИР Yandex_Bookmate 3.24 5.75
ИЭУ Yandex_Bookmate 0.55 0.5
ЛМНИ ЛитРес 50 1
ЛМНИ Yandex_Bookmate 10.30 5.32
КЗЭП Yandex_Bookmate 0.09 0.03
БизнесСофт Yandex_Bookmate 6.84 6.22
ИИБД Yandex_Bookmate 8.16 11.39
БД ЛитРес 50 1
БД Yandex_Bookmate 72.10 53.4
БД МТС_Строки 23.82 1
Для разбиения на блоки по дням можно использовать нечто вроде #25-02-02 #25-02-04.
Если все суммы проводок задаются явно, то последовательность блоков может быть любой - программы расширения при загрузке данных упорядочат их по возрастанию меток времени автоматически до формирования отчётов или обработке запросов на выполнение расчётов. Но, если какие-либо суммы проводок вычисляются спецалгоритмами или вообще спецалгоритмы построены так, чтобы автоматически генерировать последовательности проводок, то блоки проводок надо выстраивать в правильной последовательности меток, поскольку любая спецобработка производится строго сверху вниз - от начала ФМП к его концу. Тут есть исключения, но они требуют множества оговорок. Поэтому лучше придерживаться именно указанного правила.
Внутри блоков проводки выстраиваются строго в той последовательности, в которой они записаны в ФМП.
При осуществлении спецвычислений некоторые используемые для них встроенные функции производят вычисления строго ДО проводки, из которой они инициированы. Там ориентация производится не по меткам времени, а по внутреннему номеру проводки, который сквозным обрабом наращивается последовательно, невзирая на определённую метками времени последовательность блоков. То есть вычисления производятся ДО вполне конкретной проводки конкретного блока.
Метки проводок
Отдельные проводки или их совокупности могут быть специальным образом помечены. Метки могут проставляться автоматически или устанавливаться вручную.
Автоматически проставляемые метки обычно нужны для идентификации проводок, относящихся к одному документу. Например, есть чек из магазина. Это единый документ. Строки чека записываются проводками. Каждой такой строке должна быть сопоставлена метка её принадлежности к данному чеку. Чтобы не записывать одну и ту же метку в каждой строке можно указать специальную инструкцию, которая начинается с символа % и далее следует код метки или последовательность кодов меток. Далее вводятся проводки, которые должны быть ею (ими) помечены. Завершением пометки является символ % символ % без кода метки.
Например:
#25-02-06
%Ozon25-02-06
Матрас ТБанк 8831.00 1
КлавМышь ТБанк 1497.00 1
Кабель ТБанк 204.00 1
Здесь блок проводок от #25-02-06 включает данные по документу Ozon25-02-06. Конструкция %Ozon25-02-06 указывает на то, что всем последующим проводкам до одиночного символа % сопоставляется метка Ozon25-02-06.
Далее с помощью запроса @dzvp("m:Ozon25-02-06") (об отчётах см. далее) можно получить форму выборки проводок с данной меткой: Пример 01 документации
Указанный в примере запрос вывел все проводки, автоматически помеченные меткой Ozon25-02-06. Стоит отметить, что этот механизм весьма удобен при выверке чеков с большим числом позиций, поскольку в оригинале чека всегда есть сведения о его общей сумме.
Ручные метки должны проставляться в соответствующие проводки вручную. При этом они могут сочетаться с автоматически проставленными метками. Ручные метки обычно нужны для того, чтобы указать какой-либо сквозной признак операции, отражаемой конкретной проводкой. Например, если покупки приобретаются в разных магазинах попеременно, то можно дополнительно приписывать к проводкам условное обозначение этого магазина: Лента, Пятёрочка, Азбука и т.д. Эти же метки можно проставлять и автоматически, поскольку число таковых неограничено. То есть в рассмотренном выше примере можно было бы написать %Ozon25-02-06 Ozon. Тогда каждой проводке были бы одновременно сопоставлены две метки: Ozon25-02-06 и Ozon. Первую можно использовать для выверки правильности ввода чека, а вторую использовать везде в подобных чеках. Тогда в отчёты можно будет выбрать только данные по покупкам, отражённым всеми проводками ФМП с меткой Ozon.
Отчёты
В данном разделе приводится не формальное описание системы основных отчётов расширения. Формальное описание участвующих при их создании функций приводится далее.
Совокупности отчётов оформляются отдельными статьями, каждая из которых:
1. Загружает описания счетов (необязательно);
2. Загружает массив проводок (обязательно);
3. Вызывает функции расширения, обеспечивающие вывод отчётов в необходимой последовательности.
Основными типами отчётов, поддерживаемых расширением на текущий момент являются:
1. оборотная ведомость;
2. выборка проводок;
3. ведомость динамики изменения счёта;
4. итоги по корреспонденциям счетов.
Центральным отчётом является оборотная ведомость, которая содержит ссылки на вывод форм расшифровок (2-4), привязанных к её отдельным показателям. В то же время прочие разновидности форм могут быть выведены и самостоятельно, прямым указанием на формирующие их функции в тексте статьи.
Функции вывода отчётов имеют множество параметров, которые могут ограничивать:
1. Диапазон времени;
2. Состав выводимых в отчёт счетов;
3. Обрабатываемые метки проводок.
За счёт возможностей отбора данных можно включать в отчёт только определённую, интересующую пользователя информацию. Здесь имеется принципиальное отличие от обычного для многих программ обработки учётно-аналитических данных порядка вывода отчётов, когда каждый отчёт выводится обособленно, но его выводу предшествует диалог установки регулирующих вывод параметров. Например, в таких программах можно вывести оборотную ведомость за различный диапазон времени, отобрав в отчёт данные по определённым счетам. В рассматриваемом расширении диалог установки параметров отчётов не предусмотрен. Здесь для вывода отчёта с каждым набором ограничивающих параметров нужно оформлять отдельную статью или вручную править одну и ту же статью, переписывая параметры вызова конкретных функций. Это менее удобно. Однако за счёт этого при получении формы с конкретным набором параметров не нужен этап предварительной установки последних. Если статья один раз сформирована и при вызове функций указаны нужные наборы параметров, то для получения отчёта с конкретным набором параметров нужно лишь перейти по ссылке, указывающей на данную статью.
К тому в одной статье можно обеспечить вывод множества взаимосвязанных отчётов. В аналогичных программах этого обычно сделать нельзя: сначала нужно сформировать один отчёт, потом другой, потом третий и т.д.
Пример вывода серии отчётов по первичным счетам представлен статьёй, имеющей следующее содержание.
.n 2024-11. Оборотная ведомость за ноябрь 2024 года (детально)
.a С формами для выверки чеков
.d 03333
.s
;Загрузить описания счетов
@dzzs('dz/mpr/mprs.txt')
;Загрузить массив проводок
@dzzp('dz/mpr/mprp.txt')
~p=massiv("n:24-11-01 k:24-12-01")
;Получить данные оборотной ведомости по первичным счетам
~x=dzdov(p)
::2024-11. Оборотная ведомость за ноябрь 2024 года (детально)
;Вывести оборотную ведомость по полученным данным
@dzvov(x,p)
;Закомментированные функции вывода форм сверки проводок по чекам
;@dzvp("m:ЧП24-11-02")
;@dzvp("m:ЧП24-11-03")
;@dzvp("m:ЧП24-11-06")
;@dzvp("m:ЧП24-11-09")
;@dzvp("m:ЧП24-11-10")
;@dzvp("m:ЧЛ24-11-12")
;@dzvp("m:ЧП24-11-12")
;@dzvp("m:ЧП24-11-13")
;@dzvp("m:ЧП24-11-20")
;@dzvp("m:ЧП24-11-24")
;@dzvp("m:ЧП24-11-29")
::Затраты на приобретение продуктов питания
~q=dzpsov(x,'dos','Еда')
@vdm(q,1)
::Затраты на приобретение бухла
~q=dzpsov(x,'dos','Бухло')
@vdm(q,1)
::Затраты на приобретение хозтоваров
~q=dzpsov(x,'dos','Хозтовары')
@vdm(q,1)
.a С формами для выверки чеков
.d 03333
.s
;Загрузить описания счетов
@dzzs('dz/mpr/mprs.txt')
;Загрузить массив проводок
@dzzp('dz/mpr/mprp.txt')
~p=massiv("n:24-11-01 k:24-12-01")
;Получить данные оборотной ведомости по первичным счетам
~x=dzdov(p)
::2024-11. Оборотная ведомость за ноябрь 2024 года (детально)
;Вывести оборотную ведомость по полученным данным
@dzvov(x,p)
;Закомментированные функции вывода форм сверки проводок по чекам
;@dzvp("m:ЧП24-11-02")
;@dzvp("m:ЧП24-11-03")
;@dzvp("m:ЧП24-11-06")
;@dzvp("m:ЧП24-11-09")
;@dzvp("m:ЧП24-11-10")
;@dzvp("m:ЧЛ24-11-12")
;@dzvp("m:ЧП24-11-12")
;@dzvp("m:ЧП24-11-13")
;@dzvp("m:ЧП24-11-20")
;@dzvp("m:ЧП24-11-24")
;@dzvp("m:ЧП24-11-29")
::Затраты на приобретение продуктов питания
~q=dzpsov(x,'dos','Еда')
@vdm(q,1)
::Затраты на приобретение бухла
~q=dzpsov(x,'dos','Бухло')
@vdm(q,1)
::Затраты на приобретение хозтоваров
~q=dzpsov(x,'dos','Хозтовары')
@vdm(q,1)
Для просмотра результатов перейдите по ссылке: 2024-11. Оборотная ведомость за ноябрь 2024 года (детально)
Рассмотрим подробнее секцию содержание (.s) данной статьи.
Сначала функция dzzs() загружает описания счетов из файла dz/mpr/mprs.txt. Далее функция dzzp() загружает проводки из файла dz/mpr/mprp.txt. Как уже отмечалось ранее, файлы описания счетов и массива проводок могут быть составными, то есть включать команды вставки данных из других источников. После выполнения перечисленных действий описания счетов и массив проводок находятся к памяти компьютера и доступны для использования другими встроенными функциями расширения. При этом автоматически вычислены по спецалгоритмам (см. далее) суммы проводок и сформированы группы явно не заданных проводок на основе определённых спецалгоритмами правил. При блоки проводок выстроены по возрастанию рассмотренных ранее меток времени. А внутри самих блоков они размещены в порядке ввода и правил автоматического формирования на основе спецалгоритмов.
Далее конструкция ~p=massiv("n:24-11-01 k:24-12-01") (см. Порядок формирования секции Содержание для файлов статьи ) помещает в переменную p массив с двумя элементами: n и k. Элемент n определяет дату начала периода формирования оборотов по счетам. Все блоки проводок ДО указанной в нём метки времени формируют остатки счетов на НАЧАЛО периода. Если параметр n не задан или имеет пустое знечение, то остатки на начало периода устанавливаются равными нулю, а все блоки проводки используются для вычисления оборотов счетов. Параметр k устанавливает дату конца периода. Все блоки проводок ДО данной метки времени, начиная с метки времени, определённой параметром n используются для вычисления оборотов счетов. В переводе на человеческий язык в данном примере параметрами для формирования данных устанавливается ноябрь 2024 года (период с первого ноября включительно, строго ДО первого декабря).
Далее конструкция ~x=dzdov(p) присваивает переменной x двумерный массив данных оборотной ведомости, сформированными в соответствии с ограничениями, установленными элементами массива параметров p. Индексами строк являются коды первичных счетов, а каждая строка содержит данные о входящем остатке данного счёта на начало заданного периода и его дебетовом и кредитовом оборотах в стоимостном и натуральном выражении. Эти данные являются основой для вывода оборотных ведомостей с различными формами отбора счётов, а также могут быть использованы для формирования данных по агрегирующим счетам, каждый из которых обобщает остатки и обороты по совокупности первичных счетов (см. далее).
Далее конструкция @dzvov(x,p) выводит стандартную для расширения форму оборотной ведомости, основываясь на ранее сосчитанных данных, хранящихся в переменной x, а также руководствуясь параметрами отбора, указанными в массиве p. В представленном примере функция dzvov() будет использовать параметры массива p только для оформления заголовка отчёта и ссылок на его расшифровки. В общем же случае в состав параметров могут быть включены, например, данные, ограничивающие состав счетов, включаемых в данный конкретный выводимый экземпляр ведомости (например, только по заданной группе счетов). Подробное описание параметров отбора данных для функции dzvov() см. далее.
В заголовке отчёта выводятся параметры, заданные прии формировании данных и выводе отчёта. В рассматриваемом примере - это только даты начала (n:) и конца (k:) периода.
Стандартная форма оборотной ведомости имеет 5 колонок:
1. код счёта;
2. входящий остаток на начало периода;
3. дебетовый оборот счёта за период;
4. кредитовый оборот счёта за период;
5. исходящий остаток на конец периода.
Если загружены описания счетов (dzzs()) и у конкретного счёта задан параметр n (Название счёта), то его значение выводится отдельной строкой перед строкой данных об остатках и оборотах счёта.
Некоторые из реквизитов при ведённой в примере оборотной ведомости имеют форму гиперссылки. При переходе по этим ссылкам в отдельном окне (вкладке) выводится та или иная форма расшифровки данных.
Ссылка на коде счёта (колонка 1) ведёт к выводу формы о проводках, в которых данный счёт фигурировал в качестве дебетуемого или кредитуемого. В конце такой формы выводятся итоги по всем выбранным проводкам в стоимостном и натуральном выражении за выбранный период. Если счёт и дебетовался, и кредитовался, то эти итоги не имеют содержательного смысла. Если же счёт либо только дебетовался, либо только кредитовался, то итоги соответствуют либо дебетовому, либо кредитовому обороту и совпадаются с соответствующим суммарным оборотом оборотной ведомости.
Ссылка на суммах входящего остатка (колонка 2) ведёт на страницу вывода формы динамики изменения счёта, показывающей как изменялся его остаток от начала ведения учёта до даты начала периода. В этой форме выводится остаток счёта на начало периода ведения учёта (0), все проводки по счёту ДО даты начала периода, а также остаток счёта в результате осуществления каждой проводки. В последней строке выводится остаток счёта на начало исследуемого периода.
Ссылка на значении дебетового оборота (колонка 3) выводит отчёт о суммарных оборотах в дебет данного счёта с кредита других счетов, с которыми он корреспондировал в проводках за выбранный период.
Ссылка на значении кредитового оборота (колонка 4) выводит отчёт о суммарных оборотах с кредита данного счёта в дебет других счетов, с которыми он корреспондировал в проводках за выбранный период.
Ссылка на суммах исходящего остатка (колонка 5) ведёт на страницу вывода формы динамики изменения счёта, показывающей как изменялся его остаток на протяжении исследуемого периода. В этой форме выводится остаток счёта на начало заданного периода, все проводки по счёту от начала до конца периода, а также остаток счёта в результате осуществления каждой проводки. В последней строке выводится остаток счёта на конец исследуемого периода.
Далее в рассматриваемом примере приводятся закомментаренные функции вывода вывода конкретных набором проводок, помеченных определёнными метками (m:). В процессе ввода данных они использовались для выверки правильности ввода чеков за указанный период. Если снять признак комментария у любой из них (;), то при обработке текста статьи соответствующая функция выведет отчёт о проводках с заданной в запросе меткой. Логику построения меток поясним на примере. Метка ЧП24-11-02 содержательно означает, что должны выбираться проводки, соответствующие чеку Пятёрочки от 24-11-02, а ЧЛ24-11-12 - чеку Ленты от 24-11-12. Принцип выверки состоит в том, что вывод проводок функцией dzvp("m:ЧП24-11-10") сопровождается итогом по их суммам, который должен совпадать с итоговой суммой бумажного или электронного чека.
Представленный пример не ограничивается только выводом оборотной ведомости и возможным выводом форм выверки последовательностей проводок. В статье выводятся также дополнительные отчёты, собирающие определённые группы данных. В частности, это возможно благодаря тому, что проводки и описания счетов заранее загружены, а данные оборотной ведомости сформированы и записаны в переменную x.
В частности, конструкция ~q=dzpsov(x,'dos','Еда') записывает в переменную q вектор дебетовых оборотов (dos) счетов, относящихся к группе Еда (в описаниях этих счетов имеется атрибут g, в числе прочего содержащий слово Еда). В данной модели учёта счета этой группы только дебетуются. Подробнее о параметрах функции dzpsov() см. далее.
Данные вектора q передаются в функцию vdm() (строка @vdm(q,1)), которая выводит их в виде текстовой диаграммы (см. Текстовые диаграммы ).
Аналогичные формы в статье выводятся для счетов групп Бухло и Хозтовары.
Другой пример касается вывода группы отчётов о продажах книг. В статье примера загружаются соответствующие ФОС и ФМП.
.n Продажи книг за 2020 год
.a
.d 03333
.s
;Загрузка описаний счетов
@dzzs("dz/pk/pks.txt")
;Загрузка проводок
@dzzp("dz/pk/pkp.txt")
;Получить данные оборотной ведомости по первичным счетам за 2020
~p="n:2020-01 k:2021-01"
~x=dzdov(p)
::Итоги по книгам
;Выбрать данные по книгам (Совокупный дебетовый оборот)
~q=dzpsov(x,'dos','Книги')
@vdm(q,1)
::Итоги по продавцам (Кредитовый оборот)
~q=dzpsov(x,'kos','Продавцы')
@vdm(q,1)
::Оборотная ведомость за 2020 год
@dzvov(x,p)
.a
.d 03333
.s
;Загрузка описаний счетов
@dzzs("dz/pk/pks.txt")
;Загрузка проводок
@dzzp("dz/pk/pkp.txt")
;Получить данные оборотной ведомости по первичным счетам за 2020
~p="n:2020-01 k:2021-01"
~x=dzdov(p)
::Итоги по книгам
;Выбрать данные по книгам (Совокупный дебетовый оборот)
~q=dzpsov(x,'dos','Книги')
@vdm(q,1)
::Итоги по продавцам (Кредитовый оборот)
~q=dzpsov(x,'kos','Продавцы')
@vdm(q,1)
::Оборотная ведомость за 2020 год
@dzvov(x,p)
Для просмотра результатов перейдите по ссылке: Продажи книг за 2020 год
Здесь логика формирования отчётов та же, что и была рассмотрена далее. Но в примере использована другая модель учёта. В проводках о продажах книг дебетуются счета книг, а кредитуются счета их продавцов. Поэтому в остатках счетов продавцов всегда фигурируют отрицательные суммы. Абсолютная величина этих сумм интерпретируется как стоимость и количество проданных ими книг всех наименований за выбранный период времени.
Группы счетов
Первичные счета могут объединяться в группы. Один счёт может входить в произвольное число групп. Группа может иметь произвольное алфавитно-цифровое кодирование. Группы, к которым относится счёт перечисляются через пробел в предопределённом атрибуте g счёта. Например, в файле описаний счётов имеются следующие строки:
ИкраКабачковая.n Икра кабачковая разная
ИкраКабачковая.g Еда
ПивоКрепкое.n Пиво крепкое разных сортов
ПивоКрепкое.g Пиво Бухло
Гель.n Гель для мытья разный
Гель.g Хозтовары
Бугульма.n Бугульма
Бугульма.g Бухло
Капуста.n Капуста свежая
Капуста.g Еда
Данные описания счетов указывают, что счета ИкраКабачковая и Капуста относятся к группе Еда, счёт Гель - к группе Хозтовары, а счета ПивоКрепкое и Бугульма - к группе Бухло. При этом счёт ПивоКрепкое входит в две группы - Бухло и Пиво.
Группы счетов используются для выборки счетов при формировании отчётов. Указание группы в качестве одного из параметров отчётов приведёт к отбору в него данных, сформированных только по проводкам счетов данной группы. Группы счетов также могут фигурировать как инструмент отбора данных при организации спецвычислений.
Например, имеется статья, содержащая следующий код:
.n Выборка счетов группы
.a
.d 03333
.s
;Загрузить описания счетов
@dzzs('dz/mpr/mprs.txt')
;Загрузить массив проводок
@dzzp('dz/mpr/mprp.txt')
~p=massiv("n:24-11-01 k:24-12-01")
;Получить данные оборотной ведомости по первичным счетам
~x=dzdov(p)
::Оборотная ведомость за ноябрь 2024 года по счетам группы Еда
;Вывести оборотную ведомость по полученным данным
@dzvov(x,"g:Еда n:24-11-01 k:24-12-01")
.a
.d 03333
.s
;Загрузить описания счетов
@dzzs('dz/mpr/mprs.txt')
;Загрузить массив проводок
@dzzp('dz/mpr/mprp.txt')
~p=massiv("n:24-11-01 k:24-12-01")
;Получить данные оборотной ведомости по первичным счетам
~x=dzdov(p)
::Оборотная ведомость за ноябрь 2024 года по счетам группы Еда
;Вывести оборотную ведомость по полученным данным
@dzvov(x,"g:Еда n:24-11-01 k:24-12-01")
В ней, как и в приведённом ранее примере, формируются данные оборотной ведомости по первичным счетам за ноябрь 2024 года. Однако в выходную форму выводятся только данные по счетам группы Еда.
Для просмотра результатов перейдите по ссылке: Выборка счетов группы
Агрегирующие счета
Данные остатков и оборотов первичных счетов могут быть обобщены на так называемых агрегирующих счетах. Например, на уровне описаний счетов некоторым из них может быть сопоставлен один обобщающий (агрегирующий) счёт. Например, какие-то счета могут быть соотнесены с агрегирующим счётом Молочное, другие со счётом Мясное, третьи - со счётом Мучное, четвёртые - со счётом Овощи. В этом случае после выполнения операции агрегирования данных оборотной ведомости первичных счетов можно обобщить их остатки и обороты на соответствующих агрегированных счетах, а потом вывести оборотную ведомость уже относительно этих обобщённых счетов.
Типичным приложением данного подхода может быть обобщение оперативного учёта до уровня бухгалтерского. В этом случае первичным счетам, по экономическому смыслу являющимися используемыми в производстве материалами можно сопоставить бухгалтерский счёт 10 - Материалы, счетам, представляющим товарные запасы сопоставить счёт 41 - Товары, счетам станков и оборудования долгосрочного использования - счёт 01 - Основные средства. Далее нужно получить данные оборотной ведомости и агрегировать их в соответствии с данной классификацией. В результате будут получены данные оборотной ведомости счетов бухгалтерского учёта.
Каждому первичному счёту может быть сопоставлено сколько угодно агрегирующих планов счетов. Однако в каждой такой системе счетов первичному счёту может быть сопоставлен только один агрегирующий счёт. Если в данной системе (плане счетов) данному первичному счёту не сопоставляется ничего, то он попросту исключается из рассмотрения. При обработке проводок по первичным счетам он как-то влиял на данные оборотной ведомости, а при обобщении в другую систему счетов он более не нужен.
Например, ФОС содержит следующие строки:
Вермишель.n Вермишель разная
Вермишель.g Еда
Вермишель.k 1
Вермишель.aps1 Еда
Вермишель.aps2 Мучное
Горошек.n Горошек консервированный разный
Горошек.g Еда
Горошек.k 1
Горошек.aps1 Еда
Горошек.aps2 Консервы
Вино.n Вино разное
Вино.g Бухло
Вино.k 1
Вино.aps1 Бухло
Вино.aps2 Вино
Водка.n Водка разная
Водка.g Бухло
Водка.k 1
Водка.aps1 Бухло
Водка.aps2 Крепкое
ЗубПаста.n Зубная паста
ЗубПаста.g Хозтовары
ЗубПаста.k 1
ЗубПаста.aps1 Хозтовары
ЗубПаста.aps2
Еда.n Расходы и объёмы приобретения продуктов питания
Еда.k 0
Бухло.n Разная выпивка
Бухло.k 0
Хозтовары.n Все категории промышленных товаров и услуг, кроме продуктов питания
Хозтовары.k 0
Это означает, что в плане счетов aps1 счетам Вермишель и Горошек сопоставлен счёт Еда, счетам Вино и Водка - счёт Бухло, а счёту ЗубПаста - счёт Хозтовары. При этом счета Еда, Бухло и Хозтовары тоже имеют свои определения. В которых, вообще говоря, также могут иметь атрибуты, характеризующие их отнесение к более высоким уровням обобщения.
Система счетов aps2 имеет также определена для части счетов. Но для счёта ЗубПаста агрегирующий счёт не определён. Поэтому при обобщении в эту систему счетов данные по этому счёту будут исключены.
Системы счетов сопоставляются первичному счёту через атрибуты, которые могут иметь произвольное именование. При обобщении данных соответствующей функции передаётся имя этого атрибута, анализируя значение которого для каждого счёта данная функция производит подстановку, заменяя код счёта на код агрегирующего счёта. Далее, данные остатков и оборотов с одинаковыми кодами агрегирующих счетов суммируются. В результате получается обобщение данных исходных счетов.
Порядок выполнения действий по агрегированию данных рассмотрим на примере статьи сo следующим содержанием:
.n 2024-11. Оборотная ведомость за ноябрь 2024 года (сводно)
.a
.d 03333
.s
;Загрузить описания счетов
@dzzs('dz/mpr/mprs.txt')
;Загрузить массив проводок
@dzzp('dz/mpr/mprp.txt')
~p=massiv("n:24-11-01 k:24-12-01")
;Получить данные оборотной ведомости по первичным счетам
~x=dzdov(p)
;Агрегировать данные в обобщённые счета aps1
~y=dzaov(x,'aps1')
~u=massiv("n:24-11-01 k:24-12-01 a:aps1")
::2024-11. Оборотная ведомость за ноябрь 2024 года (сводно)
;Вывести оборотную ведомость по полученным данным
@dzvov(y,u)
.a
.d 03333
.s
;Загрузить описания счетов
@dzzs('dz/mpr/mprs.txt')
;Загрузить массив проводок
@dzzp('dz/mpr/mprp.txt')
~p=massiv("n:24-11-01 k:24-12-01")
;Получить данные оборотной ведомости по первичным счетам
~x=dzdov(p)
;Агрегировать данные в обобщённые счета aps1
~y=dzaov(x,'aps1')
~u=massiv("n:24-11-01 k:24-12-01 a:aps1")
::2024-11. Оборотная ведомость за ноябрь 2024 года (сводно)
;Вывести оборотную ведомость по полученным данным
@dzvov(y,u)
Для просмотра результатов перейдите по ссылке: 2024-11. Оборотная ведомость за ноябрь 2024 года (сводно)
Содержание действий отличается от рассмотренного ранее примера по выводу детальной оборотной ведомости только тем, что перед выводом отчёта первичные данные оборотной ведомости агрегируются в отдельный массив данных (~y=dzaov(x,'aps1')). В этом массиве коды первичных счетов заменены на коды агрегирующих счетов, содержащихся в их атрибуте с кодом aps1, а данные соответствующим образом просуммированы. Создание отдельного массива параметров конструкцией (~u=massiv("n:24-11-01 k:24-12-01 a:aps1")), вообще говоря, не является обязательным и нужно только для того, чтобы функция формирования отчета вывела эти данные в его заголовке.
Специальные алгоритмы
Специальные алгоритмы предназначены для реализации специфических вычислений, осуществляемых при формировании внутреннего представления массива проводок на основе их описаний в ФМП. Если во всех проводках ФМП все суммы в стоимостном и натуральном выражении заданы числами, то спецалгоритмы не используются. Однако в ряде случаев либо суммы некоторых проводок должны вычисляться на основе ранее обработанных проводок и/или параметров счетов, либо проводки вообще желательно генерировать автоматически по определённым правилам на основе ранее обработанных данных или с привлечением каких-либо внешних данных.
Типичными примерами необходимости выполнения подобных вычислений являются:
1. закрытие кредитуемого счёта (списание текущего сальдо в дебет другого счёта);
2. списание себестоимости материала по средневзвешенной цене;
3. формирование проводок начисления амортизации по заданным нормативам;
4. начисление заработной платы по групповым или индивидуальным тарифам в соответствии с часами отработанного времени;
5. и т.д.
Для решения подобных задач в расширении "Двойная запись" могут использоваться самостоятельно разрабатываемые его пользователями алгоритмы. Они могут кодироваться на языке программирования php, либо на встроенном языке системы. Размещение программного php-кода на сайте под управлением данной системы обычным пользователям запрещено и разрешено только лицам, имеющим доступ к хостингу. Однако практически любой спецалгоритм может быть реализован на основе встроенного языка программирования системы (см. Вычислительная среда ) с помощью функций данного расширения.
Для встраивания в запись проводки ссылки на алгоритм специальных вычислений используются конструкции @метод или $модуль.
Конструкция @метод предназначена для отсылки к статическому методу класса dzsa. Она может использоваться для отсылки к методам, размещённым в классе dzsa, исходный php-код которого поставляется вместе с классом dz, содержащим основные методы, выполняемые при обращении к встроенным функциям расширения. В этот класс может быть добавлен php-код нового метода, оформленный как static function. В этом случае метод - это имя метода класса dzsa. Далее рассматриваются примеры реализации такого подхода к реализации спецалгоритмов. Этот подход доступен только в том случае, если пользователь имеет высокий статус и может размещать на хостинге сайта новый программный php-код.
Конструкция $модуль предназначена для отсылки к программному модулю, реализованному на встроенном языке. В этом случае модуль - это имя секции файла той же статьи, из которой запускаются спецвычисления. Данная секция должна содержать программный код на встроенном языке вычислительной среды системы. Сам код модуля может находиться и в другом источнике (отдельном файле, секции другой статьи или книги) и импортироваться в данную секцию командами вставки (см. Вставка данных из других источников ). Если при загрузке проводок функция встречает подобную конструкцию, то производится выборка данных из секции "модуль", компиляция исходного кода и выполнение скомпилированного модуля. Данный подход доступен любому пользователю сайта, основанного на данной системе, имеющего статус не ниже, чем Писатель.
Специальные вычисления подобного рода автоматически инициируются функцией dzzp. При загрузке проводок она анализирует все входящие в неё слова. Если третьей слово проводки (сумма операции в стоимостном выражении) имеет нечисловое значение, то производится анализ данной текстовой конструкции на наличие символов @ или $ в первой позиции. Если какой-то из этих символов присутствует, то осуществляется либо вызов указанного метода из класса dzsa, либо выполняется модуль на встроенном языке по расмотренным выше правилам. В метод или модуль передаются данные текущей проводки, где обнаружена ссылка на специалгоритм. Спецалгоритм выполняется и формирует массив с данными сформированных им проводок. Эти проводки замещают проводку, из которой инициирован запуск спецалгоритма, во внутреннем представлении массива проводок. Все построенные спецалгоритмом проводки при занесении в этот массив получают последовательные внутренние номера, как и проводки, полностью оформленные вручную в ФМП.
Далее рассматривается несколько примеров реализации специалгоритмов.
Закрытие кредитумого счёта
Простейший пример необходимости использования спецалгоритмов - закрытие кредитуемого счёта. Это типовая задача бухучёта. Она возникает, например, в том случае, когда в конце периода нужно "обнулить" остаток счёта общехозяйственных расходов, перенеся все их на другой счёт (затрат, прибылей и т.д.). Для обнуления остатков нужно прокредитовать "обнуляемый" счёт на сумму его текущего остатка. По сути это проводка в которой дебетуется принимающий счёт и кредитуется "закрываемый" на сумму его текущего остатка.
Рассмотрим пример. Имеется статья содержащая следующий код:
.n Закрытие кредитуемого счёта
.a
.d 03333
.s
;Загружаем описания счетов
@dzzs("dz/sv/dzpzs_ps.txt")
;Загружаем массив проводок
@dzzp("dz/sv/dzpzs_mp.txt")
::Закрытие кредитуемого счёта
@dzvp("")
.zks
# ds ks sp np
*Возвращается готовая проводка в виде массива из массивов проводок
*Переносим дебетуемый счёт проводки
u('d')=ds
*Переносим кредитуемый счёт проводки
u('k')=ks
*Вычисляем текущие остатки кредитуемого счёта в стоимостном и натуральном выражении
z=dzoot(ks)
*Сумма = Остаток в стоимостном выражении
u('s')=z('oss')
*Количество = Остаток в натуральном выражении
u('n')=z('osn')
*Результатный массив проводок из одной проводки, которая заменит шаблон в потоке
r(0)=u
return(r)
.a
.d 03333
.s
;Загружаем описания счетов
@dzzs("dz/sv/dzpzs_ps.txt")
;Загружаем массив проводок
@dzzp("dz/sv/dzpzs_mp.txt")
::Закрытие кредитуемого счёта
@dzvp("")
.zks
# ds ks sp np
*Возвращается готовая проводка в виде массива из массивов проводок
*Переносим дебетуемый счёт проводки
u('d')=ds
*Переносим кредитуемый счёт проводки
u('k')=ks
*Вычисляем текущие остатки кредитуемого счёта в стоимостном и натуральном выражении
z=dzoot(ks)
*Сумма = Остаток в стоимостном выражении
u('s')=z('oss')
*Количество = Остаток в натуральном выражении
u('n')=z('osn')
*Результатный массив проводок из одной проводки, которая заменит шаблон в потоке
r(0)=u
return(r)
В статье загружаются следующие проводки из файла dz/sv/dzpzs_mp.txt
#25-01-10
ОР Хозтовары 1000
ОР Зарплата 2000
#25-01-11
*Списывается остаток счёта ОР на счёт УР
*Для расчёта суммы используется функция zks
УР ОР @zks
*Списывается остаток счёта УР на счёт Прибыль
;Для расчёта суммы используется модуль zks, код которого
;размещён в секции .zks статьи примера
Прибыль УР $zks
ОР Хозтовары 1000
ОР Зарплата 2000
#25-01-11
*Списывается остаток счёта ОР на счёт УР
*Для расчёта суммы используется функция zks
УР ОР @zks
*Списывается остаток счёта УР на счёт Прибыль
;Для расчёта суммы используется модуль zks, код которого
;размещён в секции .zks статьи примера
Прибыль УР $zks
Первые две проводки 25-01-10 дебетуют счёт OP (Общехозяйственные расходы) с кредита счетов Хозтовары и Зарплата на суммы 1000 и 2000 денежных единиц (д.е.). Для обработки этих проводок спецвычисления не нужны - все данные полностью определены. Легко сосчитать, что после выполнения этих проводок остаток счёта ОР составит 3000 д.е.
25-01-11 оформлена проводка:
УР ОР @zks
Для её полного формирования требуется расчёт суммы методом zks класса dzsa. Программный код этого метода определён следующим образом:
$u['d']=$ds; //Переносим дебетуемый счёт проводки
$u['k']=$ks; //Переносим кредитуемый счёт проводки
$z=dz::oot($ks); //Вычисляем текущие обороты и остатки в стоимостном и натуральном выражении
$u['s']=$z['oss']; //Сумма = Остаток в стоимостном выражении
$u['n']=$z['osn']; //Количество = Остаток в натуральном выражении
$r[]=$u; //Результатный массив проводок из одной проводки, которая заменит шаблон в потоке
return $r;
}
Метод получает четыре параметра, характеризующие текущую проводку, которая инициировала вызов метода:
$ds - код дебетуемого счёта;
$ks - код кредитуемого счёта;
$sp - сумма проводки в стоимостном выражении;
$np - сумма проводки в натуральном выражении.
Метод формирует проводку, которая заместит текущую во внутреннем массиве данных. Для этого дебетуемый и кредитуемый счета переносятся в результатную проводку без изменения. Далее выполняется специфический метод класса dz, вычисляющий текущие обороты и остатки кредитуемого счёта в стоимостном и натуральном выражении (см. далее описание функции dzoot, связанной с этим методом). Эти данные переносятся в соответствующие реквизиты новой (замещающей) проводки. Нужная проводка сформирована. Однако принимающая программа (в данном случае функция dzzp), вызвавшая этот метод ожидает получения списка проводок. Поэтому сгенерированная проводка помещается в возвращаемый массив как его единственный элемент.
Следующей проводкой является:
Прибыль УР $zks
Для её полного формирования требуется расчёт суммы модулем, содержащимся в секции zks рассматриваемой статьи. Код этой статьи и её секции zks приведён выше.
Встретив в проводке конструкцию $zks функция dzzp компилирует секцию zks файла статьи в модуль zks и исполняет его передавая в качестве параметров данные обрабатываемой проводки. Они и передаются в этот модуль. Рассмотрим реализованный в нём алгоритм вычислений.
# ds ks sp np
*Возвращается готовая проводка в виде массива из массивов проводок
*Переносим дебетуемый счёт проводки
u('d')=ds
*Переносим кредитуемый счёт проводки
u('k')=ks
*Вычисляем текущие остатки кредитуемого счёта в стоимостном и натуральном выражении
z=dzoot(ks)
*Сумма = Остаток в стоимостном выражении
u('s')=z('oss')
*Количество = Остаток в натуральном выражении
u('n')=z('osn')
*Результатный массив проводок из одной проводки, которая заменит шаблон в потоке
r(0)=u
return(r)
*Возвращается готовая проводка в виде массива из массивов проводок
*Переносим дебетуемый счёт проводки
u('d')=ds
*Переносим кредитуемый счёт проводки
u('k')=ks
*Вычисляем текущие остатки кредитуемого счёта в стоимостном и натуральном выражении
z=dzoot(ks)
*Сумма = Остаток в стоимостном выражении
u('s')=z('oss')
*Количество = Остаток в натуральном выражении
u('n')=z('osn')
*Результатный массив проводок из одной проводки, которая заменит шаблон в потоке
r(0)=u
return(r)
Строка # ds ks sp np описывает последовательность принимаемых при вызове модуля параметров. Ими являются:
ds - код дебетуемого счёта;
ks - код кредитуемого счёта;
sp - сумма проводки в стоимостном выражении;
np - сумма проводки в натуральном выражении.
В данном случае sp не является числом и требует определения.
В результатную проводку без изменений переносятся дебетуемый и кредитуемый счета. Функцией dzoot(ks) вычисляются исходящие остатки и обороты кредитуемого счёта в стоимостном и натуральном выражении, сформировавшиеся к моменту формирования новой проводки. Исходящие остатки кредитуемого счёта устанавливаются как суммы проводки в стоимостном и натуральном выражении. Далее полученная проводка заносится в возвращаемый массив как единственный элемент с нулевым индексом.
В завершении статьи выводится форма, содержащая полный список сформированных проводок. Результат см. по ссылке Закрытие кредитуемого счёта
В форме, полученной по указанной ссылке видно, что в третьей проводке, сформированной методом zks, списывается 3000 д.е. с кредита счёта OP в дебет счёта УР. В результате остаток счёта ОР обнуляется, поскольку на момент формирования этой проводки у него имелся дебетовый остаток именно в этой сумме (1000+2000). При этом на счёте УР образовался остаток в сумме 3000 д.е. Далее четвёртой проводкой закрывается также и счёт УР. С него также списывается в дебет счёта Прибыль его текущий остаток. Однако для вычисления этой суммы используется уже модуль zks, размещённый в секции .zks статьи демонстрационного примера.
Списание себестоимости материалов по средневзвешенной цене приходов
Другой типовой задачей для реализации на уровне спецалгоритмов является списание себестоимости материалов по средневзвешенной цене их закупок. Рассмотрим возможный вариант решения этой задачи на основе простого примера.
Имеется файл dz/sv/dzssc_mp.txt, содержащий следующие проводки:
#24-03-20
Доска Лабаз1 1000 100
#24-03-25
Доска Лабаз2 1200 100
#24-03-27
Стройка Доска $ssc 100
#24-04-01
Доска Лабаз3 1300 100
#24-04-02
Стройка Доска $ssc 100
Доска Лабаз1 1000 100
#24-03-25
Доска Лабаз2 1200 100
#24-03-27
Стройка Доска $ssc 100
#24-04-01
Доска Лабаз3 1300 100
#24-04-02
Стройка Доска $ssc 100
Они отражают следующие хозяйственные операции.
24-03-20 у организации Лабаз1 закуплен материал Доска в количестве 100 единиц, общей стоимостью 1000 д.е. Цена закупки единицы 10 д.е. за штуку. 24-03-25 у организации Лабаз2 закуплен тот же материал Доска также в количестве 100 ед., но уже на общую сумму 1200 д.е. Здесь цена за штуку уже 12 д.е. Итого на складе оказалось 200 ед. материала Доска на общую сумму 2200 д.е. Получается, что средняя цена единицы материала Доска составляет 11 д.е. Этот пример прост, поэтому всё легко проверить, выполняя расчёты в уме. Но в общем случае всё намного сложнее: может быть много приходов в разном количестве и с разной общей стоимостью. При этом нужно учитывать движение множества наименований материалов. Поэтому имеет смысл как-то автоматизировать вычисление операций списания стоимости материалов.
Далее 24-03-27 100 ед. материала Доска отправляет в производство, отражаемое счётом Стройка. Это отражается проводкой
Стройка Доска $ssc 100
Обработка проводки требует расчёта общей суммы списания, основываясь на величине остатков в натуральном и стоимостном выражении, а также количестве списания материала в натуральных единицах измерения. Эту работу и должен выполнять модуль ssd. Алгоритм его работы состоит в следующем. Для кредитуемого счёта вычисляются его текущие остатки в стоимостном и натуральном выражении (исходящие остатки кредитуемого счёта на момент формирования проводки). Деление остатка в стоимостном выражении на остаток в натуральном выражении даёт среднюю цену данного материала на момент списания. Умножая эту цену на списываемое количество материала в натуральном выражении получаем общую стоимость списываемого на производство данного типа материала.
Эти действия реализуются модулем ssc, содержащимся в одноимённой секции статьи со следующим кодом:
.n Списание себестоимости материальных ценностей по средней цене
.a Пример формирования проводок по списанию заданного количества материальных ценностей по их средней цене, вычисляемой модулем
.d 03333
.s
;Загружаем массив проводок
@dzzp("dz/sv/dzssc_mp.txt")
::Списание себестоимости материальных ценностей по средней цене
@dzvp("")
@dzdis("s:Доска")
.ssc
# ds ks sp np
*Получаем обороты и остаток счёта в стоимостном и натульном выражении
z=dzoot(ks)
*z('oss') - остаток в стоимостном выражении
*z('osn') - остаток в натуральном выражении
if z('osn')<>0
*Вычисляем среднюю цену на момент списания
sc=z('oss')/z('osn')
*Вычисляем себестоимость заданного в проводке количества списываемых ценностей по средней цене
r=sc*np
end
*Если r не вычислено, то это null
*Возвращается скалярное значение, которое будет подставлено в виде суммы проводки
return(r)
.a Пример формирования проводок по списанию заданного количества материальных ценностей по их средней цене, вычисляемой модулем
.d 03333
.s
;Загружаем массив проводок
@dzzp("dz/sv/dzssc_mp.txt")
::Списание себестоимости материальных ценностей по средней цене
@dzvp("")
@dzdis("s:Доска")
.ssc
# ds ks sp np
*Получаем обороты и остаток счёта в стоимостном и натульном выражении
z=dzoot(ks)
*z('oss') - остаток в стоимостном выражении
*z('osn') - остаток в натуральном выражении
if z('osn')<>0
*Вычисляем среднюю цену на момент списания
sc=z('oss')/z('osn')
*Вычисляем себестоимость заданного в проводке количества списываемых ценностей по средней цене
r=sc*np
end
*Если r не вычислено, то это null
*Возвращается скалярное значение, которое будет подставлено в виде суммы проводки
return(r)
В этом модуле принимаются стандартно передаваемые в спецалгоритм данные:
# ds ks sp np
где
ds - код дебетуемого счёта;
ks - код кредитуемого счёта;
sp - сумма проводки в стоимостном выражении;
np - сумма проводки в натуральном выражении.
В данном случае sp не является числом и требует определения. Вычисление этого значения осуществляется следующим образом. Сначала конструкция z=dzoot(ks) заносит в переменную z массив исходящих остатков и оборотов счёта, код которого содержится в переменной ks. Далее проверяется не является ли нулевым остаток счёта в натуральном выражении if z('osn')<>0. Если это условие выполняется, то вычисляется средняя цена единицы натурального учёта счёта ks как отношение исходящего остатка данного счёта в стоимостном выражении на исходящий остаток в натуральном выражении z('oss')/z('osn') и это значение записывается в переменную sc. Далее полученная средняя цена умножается на количество переданного в модуль списываемого материала в натуральном выражении: r=sc*np. И это полученное значение возвращается как результат вычисления по запрошенному алгоритму функции dzzp(), инициировавшей вызов модуля ssc. Если остаток в натуральном выражении равен нулю, то среднюю цену определить становится невозможно. Поэтому модуль вернёт значение null(). Получив такое значение функция dzzp выведет диагностическое сообщение и продолжит обработку последующих проводок.
Обращаем внимание, что здесь, в отличие от прошлого примера, возвращается скалярное значение. Вызвавшая спецалгоритм функция анализирует тип возвращённого специалгоритмом результата. Если это массив, как в прошлом примере, то вызвавшая спецалгоритм программа считает, что это массив, содержащий массив готовых проводок, которые надо внести в массив проводок вместо проводки, инициировавшей вызов спецрасчёта. Если же возвращается скаляр, то попросту заменяется сумма в стоимостном выражении в заданном вручную шаблоне проводки.
Далее в приведённом выше перечне проводок фигурирует проводка:
Доска Лабаз3 1300 100
Она отражает факт закупки 24-04-01 у организации Лабаз3 того же материала Доска в количестве 100 ед. общей стоимостью 1300 д.е. Далее ещё 100 ед. материала Доска списываются на счёт Стройка по средней цене проводкой:
Стройка Доска $ssc 100
Здесь средняя цена рассчитывается тем же модулем ssc по тому же самому алгоритму.
После загрузки проводок демонстрационный пример выводит два отчёта, которые выводят:
список сформированных проводок (@dzvp(""));
пооперационную динамику изменения остатков счёта Доска (@dzdis("s:Доска")).
Для просмотра полученных результатов перейдите по ссылке: Списание себестоимости материальных ценностей по средней цене
Для иллюстрации произведённых расчётов особенно наглядным является второй отчёт - о динамике изменения остатков счёта Доска в стоимостном и натуральном выражении. После первых двух операций, отражающих закупки материала Доска у поставщиков Лабаз1 и Лабаз2 в наличии имеется 200 ед. этого материала на общую стоимость 2200 д.е. Далее проводка от 24-03-27 списывает 100 ед. материала Доска по средней цене прихода 11 общей стоимостью 1100 д.е. В итоге неиспользованными остаются 100 ед. материала Доска общей стоимостью 1100 д.е. Далее 24-04-01 закупается ещё 100 ед. материала Доска общей стоимостью 1300 д.е. В результате этой закупки запасы материала Доска в натуральном выражении составляют 200 ед. общей стоимостью 2400 д.е. Далее опять производится списание 100 ед. материала Доска на счёт Стройка. Общая стоимость списания уже определена в сумме 1200 д.е. по средней цене единицы остатка в 12 д.е. на момент проведения этой операции.
Начисление дневной заработной платы по общим и индивидуальным тарифам
В качестве примера использования атрибутов счетов при организации спецвычислений рассмотрим упрощённый вариант решения задачи начисления дневной заработной платы по общим и индивидуальным тарифам. Постановка задачи состоит в следующем.
Сотрудникам организации начисляется заработная плата на основании отработанных ими часов и установленных тарифов. Тарифы различаются для нормальных и сверхурочных часов работы. Для большинства сотрудников действуют единые тарифы, но для некоторых по тем или иным причинам тарифы почасовой оплаты могут быть установлены индивидуально. Дневная зарплата каждому сотруднику начисляется одной проводкой, в которой в качестве натуральных единиц фигурируют отработанные часы по одному из тарифов. Чтобы не высчитывать вручную произведение конкретного тарифа на задаваемое вручную число часов в проводку записывается кодовое обозначение расчётного модуля, по имени которого вычисляется код тарифа, который должен быть применён в каждом конкретном случае.
Примеры такого рода проводок содержатся в файле dz/sv/dznzt_mp.txt:
Зарплата Иванов @zt1 8
Зарплата Иванов @zt2 2
Зарплата Петров @zt1 8
Зарплата Сидоров @zt1 8
Зарплата Сидоров @zt2 2
Зарплата Иванов @zt2 2
Зарплата Петров @zt1 8
Зарплата Сидоров @zt1 8
Зарплата Сидоров @zt2 2
С содержательной точки зрения приведённые проводки отражают факты, что сотрудники Иванов и Сидоров отработали каждый по 8 часов в соответствии с тарифом zt1 и 2 часа в соответствии с тарифом zt2, а сотрудник Петров 8 часов с оплатой по тарифу zt1. Для расчёта начисленной им зарплаты должны выполняться одноимённые модули - zt1 для расчёта по тарифу zt1, zt2 - для расчёта по тарифу zt2.
Значения самих тарифов устанавливаются в файле описания счетов dz/sv/dznzt_ps.txt следующим образом:
*Тарифы по умолчанию
$.t1 300
$.t2 500
Иванов.n Зарплата Иванова
Петров.n Зарплата Петрова
Сидоров.n Зарплата Сидорова с индивидуальными тарифами
Сидоров.t1 400
Сидоров.t2 600
Зарплата.n Общая начисленная зарплата
$.t1 300
$.t2 500
Иванов.n Зарплата Иванова
Петров.n Зарплата Петрова
Сидоров.n Зарплата Сидорова с индивидуальными тарифами
Сидоров.t1 400
Сидоров.t2 600
Зарплата.n Общая начисленная зарплата
Здесь часть тарифов установлена по умолчанию, конструкциями:
$.t1 300
$.t2 500
Специальный счёт $ может устанавливать значения атрибутов счетов по умолчанию. При обращении с запросом на получение значения атрибута какого-либо счёта сначала система ищет указанный атрибут непосредственно привязанный к этому счёту. Если это значение имеется, то используется именно оно. Если же запрошенный атрибут у данного счёта не найден, то делается попытка найти значение этого атрибута по умолчанию, на счёте $.
Из приведённого описания счетов видно, что у счетов Иванов и Сидоров атрибуты t1 и t2 не заданы. Значит при попытке запроса значений этих атрибутов у этих счетов будут использоваться их значения по умолчанию. У счёта Сидоров значения атрибутов t1 и t2 заданы. Следовательно при обращении к этим атрибутам для счёта Сидоров будут использоваться именно они.
Статья, реализующая вычисления данного демонстрационного примера содержится в файле dz/sv/dznzt.s и имеет следующий код:
.n Начисление дневной заработной платы по тарифам
.a
.d 03333
.s
;Загружаем описания счетов
@dzzs("dz/sv/dznzt_ps.txt")
;Загружаем массив проводок
@dzzp("dz/sv/dznzt_mp.txt")
::Начисление дневной заработной платы по тарифам
@dzvp("")
.zt1
# ds ks sp np
*Начисление дневной зарплаты по тарифу t1
return(vm('ztx',ds,ks,sp,np,'t1'))
.zt2
# ds ks sp np
*Начисление дневной зарплаты по тарифу t2
return(vm('ztx',ds,ks,sp,np,'t2'))
.ztx
# ds ks sp np kt
*vzp(ds,ks,sp,np,kt)
*ds - счёт затрат дебетуется
*ks - зарплатный счёт сотрудника кредитуется
*np - число отработанных часов или долей дня
*kt - код тарифа
*Ищем величину тарифа по его коду как свойство в зарплатном счёте сотрудника
*Если индивидуальный тариф не установлен, то dzpzas вернёт общий для всех тариф
sum=dzpzas(ks,kt)
if nz(sum)
*Не получается найти тариф
return(sum)
end
*Возвращаем произведение тарифа на число отработанных часов (долей дня)
return(sum*np)
.a
.d 03333
.s
;Загружаем описания счетов
@dzzs("dz/sv/dznzt_ps.txt")
;Загружаем массив проводок
@dzzp("dz/sv/dznzt_mp.txt")
::Начисление дневной заработной платы по тарифам
@dzvp("")
.zt1
# ds ks sp np
*Начисление дневной зарплаты по тарифу t1
return(vm('ztx',ds,ks,sp,np,'t1'))
.zt2
# ds ks sp np
*Начисление дневной зарплаты по тарифу t2
return(vm('ztx',ds,ks,sp,np,'t2'))
.ztx
# ds ks sp np kt
*vzp(ds,ks,sp,np,kt)
*ds - счёт затрат дебетуется
*ks - зарплатный счёт сотрудника кредитуется
*np - число отработанных часов или долей дня
*kt - код тарифа
*Ищем величину тарифа по его коду как свойство в зарплатном счёте сотрудника
*Если индивидуальный тариф не установлен, то dzpzas вернёт общий для всех тариф
sum=dzpzas(ks,kt)
if nz(sum)
*Не получается найти тариф
return(sum)
end
*Возвращаем произведение тарифа на число отработанных часов (долей дня)
return(sum*np)
В частности в ней содержатся секции с именами zt1, zt2, ztx. Они содержат исходный код модулей, осуществляющих специальные вычисления. Привязка в проводках производится к модулям в секциях zt1 и zt2 (@zt1, @zt2). Однако каждый из них выполняет совершенно однотипные вычисления, которые отличаются только привязкой к кодам атрибутов обрабатываемых счетов. Поэтому сами по себе модули zt1, zt2 выполняют лишь передаточную функцию, вызывая для выполнения самих вычислений один и тот же модуль ztx, но передавая ему разные параметры. В данном случае отличается только код тарифа - атрибута обрабатываемого счёта, который должен задействоваться в расчётах.
Вычисления в модуле ztx производятся по следующим правилам.
Конструкция # ds ks sp np kt принимает значения передамаемых модулю данных. Стандартно в модуль выполнения спецвычислений передаются параметры обрабатываемой проводки, которые уже рассматривались в прошлых примерах. Это первые четыре параметра. Пятый параметр - это код атрибута счёта, содержащего значение тариф.
Сначала конструкция sum=dzpzas(ks,kt) выбирает значение атрибута счёта kt счёта ks. Функция dzpzas(ks,kt) производит это действие по рассмотренным ранее принципам: сначала ищется значение атрибута у самого счёта, а если такой атрибут у данного счёта не определён, то ищется значение этого атрибута по умолчанию на специальном счёте $. Если и там нет такого атрибута, то возвращается null(). Формальное описание функции dzpzas() приведено далее.
Если значение нужного атрибута найдено, то возвращается перемноженное значение найденного тарифа на число часов отработанного в соответствии с ним времени, содержащегося в переменной np (return(sum*np)).
Для просмотра формируемых статьёй проводок перейдите по ссылке: Начисление дневной заработной платы по тарифам
Из приведённых данных видно, что зарплата Иванову и Петрову начислена по общим тарифам (в соответствии со значениями атрибутов счетов, заданных по умолчанию), а Сидорову в соответствии с его индивидульными тарифами (прямо установленными атрибутами счёта Сидоров). Если Вы внимательно прочитали предшествующий текст, то станет понятно почему.
Начисление амортизации линейным методом
В данном примере рассматривается совместное задействование использования в спецалгоритмах значений атрибутов счетов и вычислений, произведённых по данным до текущей проводки при решении задачи начисления линейной амортизации основных средств. Также здесь используются некоторые специфические приёмы организации системы задействованных счетов.
Постановка задачи состоит в следующем. Имеются счета, на которых учитывается первоначальная стоимость конкретных объектов основных средств. Каждый раз за определённый период, но не реже, чем раз в год, на них должна начисляться амортизация, которая учитывается на других счетах, которые должны каким-то образом увязываться со счетами учёта этих конкретных объектов. Проводки формируются именно по этим, дополнительным счетам учёта амортизации. В рамках возможностей раасширения "Двойная запись" задача может быть решена различными способами. Здесь рассматривается лишь один из возможных.
Файл dz/sv/dzaos_ps.txt содержит следующее описание используемых счетов:
;Норму годовой амортизации для данного примера алгоритма её начисления
;можно задать как атрибут либо счёта самого объекта,
;либо как атрибут счёта учёта накопленной на объект амортизации
;Счёт учёта первоначальной стоимости объекта
ТокСтанок.n Токарный станок
;Норма годовой амортизации в % задана как атрибут счёта
ТокСтанок.na 50
;Счёт учёта амортизации счёта ТокСтанок
ТокСтанокZ.n Амортизация токарного станка ТокСтанок
;Счёт учёта первоначальной стоимости объекта
ШлифСтанок.n Шлифовальный станок
;Счёт учёта амортизации
ШлифСтанокW.n Амортизация шлифовального станка
;Норма годовой амортизации в % задана как атрибут счёта учёта амортизации
ШлифСтанокW.na 25
;можно задать как атрибут либо счёта самого объекта,
;либо как атрибут счёта учёта накопленной на объект амортизации
;Счёт учёта первоначальной стоимости объекта
ТокСтанок.n Токарный станок
;Норма годовой амортизации в % задана как атрибут счёта
ТокСтанок.na 50
;Счёт учёта амортизации счёта ТокСтанок
ТокСтанокZ.n Амортизация токарного станка ТокСтанок
;Счёт учёта первоначальной стоимости объекта
ШлифСтанок.n Шлифовальный станок
;Счёт учёта амортизации
ШлифСтанокW.n Амортизация шлифовального станка
;Норма годовой амортизации в % задана как атрибут счёта учёта амортизации
ШлифСтанокW.na 25
В данном примере используются два счёта учёта основных средств: ТокСтанок и ШлифСтанок. У счёта ТокСтанок задан атрибут na, имеющий значение 50. Содержательный смысл атрибута na состоит в том, что он выражает годовую норму амортизации объекта, учитываемого на счёте ТокСтанок в процентах от его учётной стоимости. В данном случае - это 50%. То есть за год начисляется амотризация в половину первоначальной стоимости и потому объект будет полностью самортизирован на 2 года.
У счёта ШлифСтанок атрибут na не определён.
Для учёта амортизации по данным объектам введены дополнительные счета: ТокСтанокZ и ШлифСтанокW. Коды этих счетов отличаются от кодов счетов учёта самих объектов только одной дополнительной последней буквой. При этом на счёте ШлифСтанокW определён атрибут na со значением, равным 25. Его смысл тот же самый, что и у атрибута na счёта ТокСтанок - он выражает годовую норму амортизации объекта ШлифСтанок в процентах.
Модуль начисления амортизации должен автоматически формировать или не формировать проводки по начислению амортизации конкретного объекта. При этом должна учитываться ранее накопленная амортизация. Если она меньше первоначальной стоимости, то проводка формируется. Если накопленная амортизация равна или больше первоначальной стоимости, то проводка начисления амортизации не формируется.
Проводки для данной модели учёта содержатся в файле dz/sv/dzaos_mp.txt:
;Поступление объектов основных средств в декабре 2019
#2019-12
ТокСтанок Поставщики 48000
ШлифСтанок Поставщики 96000
#2020
;Начисление амортизации сразу за весь 2020 год
Производство ТокСтанокZ $alg
Производство ШлифСтанокW $alg
#2021
;Начисление амортизации сразу за весь 2021 год
Производство ТокСтанокZ $alg
Производство ШлифСтанокW $alg
#2022
;Начисление амортизации сразу за весь 2022 год
Производство ТокСтанокZ $alg
Производство ШлифСтанокW $alg
#2023
;Начисление амортизации сразу за весь 2023 год
Производство ТокСтанокZ $alg
Производство ШлифСтанокW $alg
#2019-12
ТокСтанок Поставщики 48000
ШлифСтанок Поставщики 96000
#2020
;Начисление амортизации сразу за весь 2020 год
Производство ТокСтанокZ $alg
Производство ШлифСтанокW $alg
#2021
;Начисление амортизации сразу за весь 2021 год
Производство ТокСтанокZ $alg
Производство ШлифСтанокW $alg
#2022
;Начисление амортизации сразу за весь 2022 год
Производство ТокСтанокZ $alg
Производство ШлифСтанокW $alg
#2023
;Начисление амортизации сразу за весь 2023 год
Производство ТокСтанокZ $alg
Производство ШлифСтанокW $alg
Здесь макеты проводок бездумно скопированы сразу на несколько лет вперёд. При этом для их формирования задействуется алгоритм, содержащийся в модуле alg. Предполагается, что он должен формировать (или не формировать) проводки по начислению амортизации сразу за год.
Демонстрация возможного способа решения этой задачи приводится в статье, содержащейся в файле dz/sv/dzaos.s, имеющей следующий код:
.n Начисление амортизации линейным методом
.a
.d 03333
.s
;Загружаем описания счетов
@dzzs("dz/sv/dzaos_ps.txt")
;Загружаем массив проводок
@dzzp("dz/sv/dzaos_mp.txt")
::Начисление амортизации линейным методом
@dzvp("")
@dzdis("s:ТокСтанокZ")
@dzdis("s:ШлифСтанокW")
.alm
*Начисление амортизации за месяц
# ds ks sp np
return(vm('alx',ds,ks,sp,np,1))
.alk
*Начисление амортизации за квартал
# ds ks sp np
return(vm('alx',ds,ks,sp,np,4))
.alg
*Начисление амортизации за год
# ds ks sp np
return(vm('alx',ds,ks,sp,np,12))
.alx
# ds ks sp np km
*Модуль начисления амортизации линейным методом за заданное число месяцев
*ds - дебетуемый счет (счёт списания затрат)
*ks - кредитуемый счёт (счёт накопления амортизации)
*sp - $alm, $alk или $alg
*np - (количество в натуральном выражении) не имеет значения для алгоритма
*km - количество месяцев, за которые начисляется амортизация
*Получаем код счёта амортизируемого объекта
*Счёт начисления амортизации должен отличаться от него ЛЮБЫМ одним дополнительным символом в конце кода
*Просто отбрасываем последний символ
so=substr(ks,0,-1)
*Текущая стоимость объекта может отличаться от первоначальной переоценками, осуществляемыми
*проводками по дебету (увеличение) или кредиту (уменьшение) стоимости объекта
*Поэтому амортизируемая стоимость равна текущему остатку счёта данного объекта
*Получаем обороты и остатки счёта объекта на текущий момент ДО формирования проводки
z=dzoot(so)
*Амортизируемая стоимость
as=z('oss')
* Получаем обороты и остатки счёта накопленной амортизации объекта на текущий момент ДО формирования проводки
z=dzoot(ks)
*Поскольку счёт всегда кредитуется, то его остаток отрицателен
na=abs(z('oss'))
*Остаточная стоимость
os=as-na
*Если накопленная амортизация с точностью до погрешности вычислений равна амортизируемой стоимости,
*то ничего не начисляем и проводка не будет сформирована
if abs(os)<0.01
return(false())
end
*Если ранее были выполнены какие-то ошибочные проводки по начислению амортизации свыше стоимости объекта,
*то убираем переначисленную амортизацию по кредиту счёта списания затрат и дебету счёта амортизации
*на сумму переначисления
if os<0
r(0,'d')=ks
r(0,'k')=ds
r(0,'s')=abs(os)
return(r)
end
*Рассчитываем амортизацию
*Выбираем годовую норму амортизации из свойства счёта начисления или свойства счёта самого объекта
*Это свойство должно иметь имя na
*Сначала пытаемся найти в атрибуте na счёта начисления амортизации
gna=dzpzas(ks,'na')
*Если атрибут na отсутствует, то ищем его на счёте самого объекта
if nz(gna)
gna=dzpzas(so,'na')
end
*Если и тут не найдено (нет значения - NULL), то возвращаем NULL
if nz(gna)
return(gna)
end
*Вычисляем амортизацию линейным методом с учётом заданного числа месяцев
*Норма задана в процентах!!!
sa=as*gna*km/1200
*Возвращаем скаляр, который будет подставлен как сумма проводки
return(sa)
.a
.d 03333
.s
;Загружаем описания счетов
@dzzs("dz/sv/dzaos_ps.txt")
;Загружаем массив проводок
@dzzp("dz/sv/dzaos_mp.txt")
::Начисление амортизации линейным методом
@dzvp("")
@dzdis("s:ТокСтанокZ")
@dzdis("s:ШлифСтанокW")
.alm
*Начисление амортизации за месяц
# ds ks sp np
return(vm('alx',ds,ks,sp,np,1))
.alk
*Начисление амортизации за квартал
# ds ks sp np
return(vm('alx',ds,ks,sp,np,4))
.alg
*Начисление амортизации за год
# ds ks sp np
return(vm('alx',ds,ks,sp,np,12))
.alx
# ds ks sp np km
*Модуль начисления амортизации линейным методом за заданное число месяцев
*ds - дебетуемый счет (счёт списания затрат)
*ks - кредитуемый счёт (счёт накопления амортизации)
*sp - $alm, $alk или $alg
*np - (количество в натуральном выражении) не имеет значения для алгоритма
*km - количество месяцев, за которые начисляется амортизация
*Получаем код счёта амортизируемого объекта
*Счёт начисления амортизации должен отличаться от него ЛЮБЫМ одним дополнительным символом в конце кода
*Просто отбрасываем последний символ
so=substr(ks,0,-1)
*Текущая стоимость объекта может отличаться от первоначальной переоценками, осуществляемыми
*проводками по дебету (увеличение) или кредиту (уменьшение) стоимости объекта
*Поэтому амортизируемая стоимость равна текущему остатку счёта данного объекта
*Получаем обороты и остатки счёта объекта на текущий момент ДО формирования проводки
z=dzoot(so)
*Амортизируемая стоимость
as=z('oss')
* Получаем обороты и остатки счёта накопленной амортизации объекта на текущий момент ДО формирования проводки
z=dzoot(ks)
*Поскольку счёт всегда кредитуется, то его остаток отрицателен
na=abs(z('oss'))
*Остаточная стоимость
os=as-na
*Если накопленная амортизация с точностью до погрешности вычислений равна амортизируемой стоимости,
*то ничего не начисляем и проводка не будет сформирована
if abs(os)<0.01
return(false())
end
*Если ранее были выполнены какие-то ошибочные проводки по начислению амортизации свыше стоимости объекта,
*то убираем переначисленную амортизацию по кредиту счёта списания затрат и дебету счёта амортизации
*на сумму переначисления
if os<0
r(0,'d')=ks
r(0,'k')=ds
r(0,'s')=abs(os)
return(r)
end
*Рассчитываем амортизацию
*Выбираем годовую норму амортизации из свойства счёта начисления или свойства счёта самого объекта
*Это свойство должно иметь имя na
*Сначала пытаемся найти в атрибуте na счёта начисления амортизации
gna=dzpzas(ks,'na')
*Если атрибут na отсутствует, то ищем его на счёте самого объекта
if nz(gna)
gna=dzpzas(so,'na')
end
*Если и тут не найдено (нет значения - NULL), то возвращаем NULL
if nz(gna)
return(gna)
end
*Вычисляем амортизацию линейным методом с учётом заданного числа месяцев
*Норма задана в процентах!!!
sa=as*gna*km/1200
*Возвращаем скаляр, который будет подставлен как сумма проводки
return(sa)
Статья содержит секции alm, alk, alg и alx. Они содержат программные модули. Имена alm, alk, alg могут непосредственно задаваться в проводках. Они предназначены: alm - для начисления амортизации за месяц, alk - за квартал, alg - за год. Все они являются переходниками к модулю alx, реализующему вычисления в зависимости от заданной продолжительности периода.
Базовый модуль alx реализует следующий алгоритм.
Сначала конструкция so=substr(ks,0,-1) записывает в переменную so - код счёта объекта основных средств, на который данной проводкой начисляется амортизация. Как мы договорились и как представлено в описаниях счетов для начисления амортизации используется счёт, идентичный счёту самого объекта, но с добавление в конце одного произвольного символа. Этот последний символ в данной конструкции и отбрасывается. Теперь переменная so содержит код счёта, учитывающего сам объект.
Далее определяется амортизируемая стоимость объекта. Это текущий исходящий остаток счёта, учитывающего объект. Для определения этого остатка конструкцией z=dzoot(so) вычисляются текущие остатки и обороты счёта, код которого содержится в переменной so. Эти данные попадают в массив z. Его компонента с индексом oss содержит требуемую величину (полное описание функции dzoot(so) приводится ниже). Конструкция as=z('oss') переносит записывает амортизируемую стоимость в переменную as. Обращаем внимание, что реализованный в примере алгоритм учитывает возможность изменения амортизируемой стоимости объекта, которая потенциально может накапливать стоимость его ремонтов и переоценок. Но в любом случае на момент начисления амортизации амортизируемая стоимость - это исходящий остаток счёта, учитывающего стоимость объекта на текущий момент.
Далее конструкцией z=dzoot(ks) вычисляются обороты и остатки счёта накопленной амортизации объекта на текущий момент. При реализуемой в данном примере модели учёта счёт начисления амортизации всегда только кредитуется. Поэтому его исходящий остаток отрицателен. Поэтому накопленная амортизация вычисляется как абсолютная величина исходящего его остатка конструкцией
na=abs(z('oss'))
Далее конструкцией os=as-na определяется остаточная стоимость объекта как разность между амортизируемой стоимостью и накопленной амортизацией.
Если объект полностью самортизирован - остаточная стоимость равна или почти равна с точностью до погрешности вычислений нулю, то проводка не формируется и модуль завершает свою работу, возвращая вызвавшей его функции dzzp() значение false():
if abs(os)<0.01return(false())
end
Если ранее были выполнены какие-то ошибочные проводки по начислению амортизации свыше амортизируемой стоимости объекта, то убираем переначисленную амортизацию по кредиту счёта списания затрат и дебету счёта амортизации на сумму переначисления:
if os<0r(0,'d')=ks
r(0,'k')=ds
r(0,'s')=abs(os)
return(r)
end
Для этого формируется проводка в которая счёт начисления амортизации объекта дебетуется, а счёт затрат проводки кредитуется на абсолютную величину остаточной стоимости, которая в данном случае оказалась отрицательной (объект ошибочно переамортизирован).
Когда все проверки выполнены можно переходить к штатному случаю формирования проводки по начислению амортизации.
Первым делом для этого нужно найти норму амортизации объекта. Сначала осуществляется поиск атрибута na на самом счёте учёта объекта конструкцией gna=dzpzas(ks,'na'). Если этот атрибут на счёте не обнаружен, то значением переменной gna будет null() (нет значения). Если этот факт подтвержадется, то производится поиск атрибута na уже в описаниях счёта начисления амортизации на этот объект:
if nz(gna)gna=dzpzas(so,'na')
end
Если и тут искомый атрибут не найден, то возвращается значение переменной gna равной null() и проводка не будет сформирована, а пользователь получит от функции dzzp() предупреждающее сообщение.
if nz(gna)return(gna)
end
Если же всё нормально, норма амортизации как значение атрибута na найдена, то производится расчёт суммы амортизации конструкцией
sa=as*gna*km/1200. Здесь амортизируемая стоимость (as) умножается на норму амортизации (gna - процентов за год), умножается на количество месяцев, за которые начисляется амортизация (1,4,12) и всё это делится на 1200 (12 месяцев * 100%).
Для вывода результатов расчётов и сформированных по ним проводок перейдите по ссылке: Начисление амортизации линейным методом
По приведённой ссылке выводятся три формы. Первая содержит сформированные по годам проводки начисления амортизации на рассматриваемые объекты основных средств. Две другие объясняют динамику изменения состояния счётов начисления амортизуции по годам. Из этих форм видно, что в результате выполнения модуля alg для объекта ТокСтанок на счёт ТокСтанокZ амортизация начислялась только в 2020 и 2021 году в сумме 50% от стоимости объекта, как это и установлено нормой амортизации (атрибутом na счёта). В результате амортизируемая стоимость стала равной нулю и в последующие годы проводки не формировались, несмотря на то, что их шаблоны для этих лет были заданы (см. выше список проводок). Для объекта ШлифСтанок амортизация начислялась все четыре года, поскольку здесь норма амортизации была установлена равной 25%. В итоге за этот срок объект полностью самортизировался.
Функции расширения "Двойная запись"
Далее приводится формальное описание функций расширения "Двойная запись", которые могут быть использованы при формировании статей, а также в программах на встроенном языке системы.
dzzs - Загрузить описания счетов
Функция dzzs(fos) используется для загрузки описаний счетов из текстового файла, относительное имя которого содержится в передаваемом ей параметре. Файл описаний счетов может содержать команды вставки данных из внешних источников. См. Вставка данных из других источников. В потоке описаний счетов может быть сколько угодно комментариев - строк, начинающихся с символов и *. Эти строки при загрузке данных полностью игнорируются.
dzpzas - Получить значение атрибута счёта
Функция dzpzas(s,a) позволяет получить значение заданного атрибута заданного счёта или массив значений всех атрибутов счёта. Параметр s определяет код искомого счёта, а параметр a - имя атрибута. Если параметр a не задан или имеет пустое значение, то возвращается массив значений всех атрибутов счёта s, которые заданы в ФОС. Если параметр a задан, то возвращается его значение, если атрибут с таким кодом имеется в описании счёта s. Если атрибут a для этого счёта не задан, то функция пытается найти вернуть значение данного атрибута по умолчанию как атрибут a счёта с кодом $. Если значение по умолчанию не установлено, то возвращается значение null().
dzizas - Изменить значение атрибута счёта
Функция dzizas(s,a,z) назначает z значением атрибута a счёта s. Если атрибут a у счёта s отсутствует, то он будет создан. Все параметры являются обязательными.
dzppg - Проверка принадлежности к группе счетов
Функция dzppg(ks,kg) проверяет вхождение счёта ks в группу kg. Сначала определяется наличие описателя g у счёта ks. Если описатель отсутствует, то возвращается значение 0. Если свойство g у счёта ks задано, то проверяется вхождение кода kg в заданный им список. Список групп может быть задан как строкой словами, которой являются коды групп, в которые входит счёт, или массивом, элементами которого являются коды групп. Если kg входит в перечень групп счёта, то возвращается значение 1, в противном случае - значение 0.
dzpvs - Построение выборки счетов, входящих в агрегирующий счет
Функция dzpvs(s,a) возвращает массив, содержащий все счета, у которых атрибут a установлен в значение s.
dzksm - Контроль соответствия маске счёта
Функция dzksm(ms,ks) проверяет соответствие счёта ks маске ms. Вычисляется длина кода - k, содержащегося в ms. Если первые k символов ks в точности равны значению параметра ms, то возвращается 1, в противном случае - 0. Если длина строки ks меньше длины строки ms, то возвращается 0.
dzvsg - Выборка всех счетов группы
Функция dzvsg(g) возвращает массив с кодами всех счетов, входящих в группу g.
dzops - Обновление плана счетов
Функция dzops(ma) подготавливает данные для обновления файла описаний счетов. Сканируются все загруженные ранее проводки и из них выбираются все задействованные в них счета. Если какие-либо из задействованных в проводках счетов, отсутствуют в описаниях, то такие описания создаются и в них записываются пустые значения предопределённых атрибутов. Далее анализируется наличие параметра ma. Он может быть массивом, элементы которого являются кодами новых атрибутов счетов, или строкой, содержащей разделённые пробелами слова, выражающие коды новых атрибутов. К описаниям всех счетов добавляются описания новых атрибутов там, где они отсутствуют, с пустыми значениями новых атрибутов. Обновлённая система описаний счетов конвертируется в последовательность строк, которая выводится в поле ввода многострочного текста. Пользователь может проверить корректность подстановок, скопировать полученный текст в буфер обмена и далее использовать эти данные для модификации ФОС.
dzzp - Загрузить проводки
Функция dzzp(fmp) загружает файл массива проводок и конвертирует его во внутренее представление, готовое для использования другими функциями расширения. Файл массива проводок может содержать команды вставки данных из внешних источников. См. Вставка данных из других источников
В потоке проводок может быть сколько угодно комментариев - строк, начинающихся с символов и *. Эти строки при загрузке данных полностью игнорируются.
Отдельные строки могут обрабатываться специальным образом. Если строка начинается с символа #, то её продолжение интерпретируется как метка времени - произвольная последовательность символов без пробелов и табуляций, идентифицирующая время осуществления последующих проводок. Установленная метка времени распространяется на все последующие проводки до определения новой метки времени.
Если для формирования проводок не используются специальные вычисления, то блоки проводок, соответствующие разным меткам времени могут вводиться в произвольной последовательности меток. Если же хотя бы для обработки одной проводки используются спецвычисления, то блоки настоятельно рекомендуется вводить в последовательности, упорядоченной по возрастанию меток времени.
При загрузке проводок они группируются в блоки в соответствии с метками времени. Если суммы некоторых проводок требуют расчёта по специальным алгоритмам, то необходимые вычисления производятся и соответствующие символьные коды сумм заменяются вычисленными числовыми значениями. Кроме того специальные алгоритмы могут добавлять в массив проводок полностью автоматически сформированные проводки.
Помимо меток времени в потоке проводок могут содержаться операции вызова встроенных функций и/или операции присваивания значений переменным. Если строка начинается с символа @, то её последующий текст интерпретируется как функция с параметрами. Данная функция безоговорочно выполняется. Если строка начинается с символа ~, то последующих текст интерпретируется как операция присваивания значения переменной. Логика осуществления операций @ и ~ при обработке потока проводок полностью идентична правилам их осуществления при обработке потока текста статьи. Cм. раздел "Переменные" в статье Порядок формирования секции Содержание для файлов статьи
Каждая ординарная строка, представляющая проводку должна иметь как минимум три разделённых произвольным числом пробелов слова. Первое интерпретируется как код дебетуемого счёта, второе - как код кредитуемого счёта, третье - как сумма проводки в стоимостном выражении. Сумма может иметь представление: @метод или $модуль. Примеры использования этих конструкций рассматривались ранее.
Конструкция @метод предназначена для отсылки к статическому методу класса dzsa. Она может использоваться для отсылки к методам, размещённым в классе dzsa, исходный php-код которого поставляется вместе с классом dz, содержащим основные методы, выполняемые при обращении к встроенным функциям расширения. В этот класс может быть добавлен php-код нового метода, оформленный как static function. В этом случае метод - это имя метода класса dzsa. Далее рассматриваются примеры реализации такого подхода к реализации спецалгоритмов. Этот подход доступен только в том случае, если пользователь имеет высокий статус и может размещать на хостинге сайта новый программный php-код.
Конструкция $модуль предназначена для отсылки к программному модулю, реализованному на встроенном языке. В этом случае модуль - это имя секции файла той же статьи, из которой запускаются спецвычисления. Данная секция должна содержать программный код на встроенном языке вычислительной среды системы. Сам код модуля может находиться и в другом источнике (отдельном файле, секции другой статьи или книги) и импортироваться в данную секцию командами вставки (см. Вставка данных из других источников ). Если при загрузке проводок функция встречает подобную конструкцию, то производится выборка данных из секции "модуль", компиляция исходного кода и выполнение скомпилированного модуля. Данный подход доступен любому пользователю сайта, основанного на данной системе, имеющего статус не ниже, чем Писатель.
В метод или модуль передаются данные текущей проводки, где обнаружена ссылка на спецалгоритм. Спецалгоритм выполняется и формирует либо значение суммы (скаляр), либо массив с данными сформированных им проводок. Если возвращёно скалярное значение, то dzzp() просто подставит его в качестве суммы проводки в стоимостном выражении (всегда третий элемент проводки). Если спецалгоритм вернул массив, то dzzp() интепретирует его как перечень проводок, которые должны замещать проводку, инициировавшую запуск спецалгоритма. Все построенные спецалгоритмом проводки при занесении во внутреннее представление массива проводок получают последовательные внутренние номера, как и проводки, полностью оформленные вручную в ФМП.
Помимо трёх основных компонент проводки она может включать и дополнительные элементы. Четвёртое слово проводки, если оно имеется, интерпретируется как сумма проводки в натуральном выражении. В данной версии расширения установка конкретных единиц измерения для таких данных не предусмотрена. Предполагается, что корректность ввода натуральных данных на каждом счёте с точки зрения единства применяемых единиц измерения контролируется самим пользователем.
Пятым и последующим необязательными компонентами проводки являются метки. Их назначение, порядок формирования и правила интерпретации были рассмотрены в этой статье ранее в разделе Метки проводок. Метки проводок, если они указаны вручную или сформированы автоматически также записываются в массив внутреннего представления проводок.
В результате выполнения функции dzzp все проводки (введённые вручную и сформированные автоматически) являются полностью доступными для использования в расчётах по формированию отчётов или для вычисления произвольных показателей иными функциями расширения.
dzdp - Добавить проводку с внутренним текущим номером
Функция dzdp(ds,ks,sp,np) автоматически формирует новую проводку в которой дебетуется счёт ds, кредитуется счёт ks, на сумму sp в стоимостном выражении и величину np в натуральном выражении. Проводке присваивается очередной врутрисистемный номер. Кроме того, добавляемой проводке могут быть сопоставлены ручные и автоматически формируемые метки, которые предварительно установлены специальным алгоритмом. Функцию имеет смысл использовать только внутри специальных алгоритмов, автоматически вызываемых при обработке проводок функцией dzzp. См. примеры выше.
dzknm - Контроль наличия меток в проводке
Функция dzknm(dp,mm) проверяет наличие всех проводок списка mm в проводке, определяемой массивом dp. Массив данных проводки должен иметь более 4 элементов. Обязательными из них являются элементы с индексами:
d - Дебетуемый счёт;
k - Кредитуемый счёт;
s - Сумма проводки в стоимостном выражении;
n - Сумма проводки в натуральном выражении.
Элементы с другими индексами интерпретируются как метки. Именно по этим данным определяется результат. Если все метки списка mm содержатся в проводке, то возвращается значение 1, в противном случае возвращается 0.
dzdov - Формирование данных оборотной ведомости по всем первичным счетам с учётом меток проводок
Функция dzdov(p) возвращает массив данных оборотной ведомости первичных счетов, соответствующих ограничениям, установленным списком параметров p. Список параметров может содержать любой набор параметров, но при формировании выходных данных функция dzdov() учитывает только параметры с идентификаторами n, k и m.
Элемент n определяет дату начала периода формирования оборотов по счетам. Все блоки проводок ДО указанной в нём метки времени формируют остатки счетов на НАЧАЛО периода. Если параметр n не задан или имеет пустое знечение, то остатки на начало периода устанавливаются равными нулю, а все блоки проводки используются для вычисления оборотов счетов. Параметр k устанавливает дату конца периода. Все блоки проводок ДО данной метки времени, начиная с метки времени, определённой параметром n используются для вычисления оборотов счетов. Параметр m определяет перечень меток, которыми должны быть помечены подлежащие обработке проводки. Если должно проверяться наличие более одной метки, то их перечень в параметре m задаётся через запятую.
Пример вызова функции dzdov() непосредственно в тексте статьи с указанием параметров:
~x=dzdov("n:24-12-01 k:25-01-01 m:Ozon")
Вызов функции в данной форме приведёт к записи в переменную x данных по остаткам и оборотам счетов, вычисленных только по проводкам с установленной меткой "Ozon". Входящие остатки счетов будут формироваться по всем блокам проводок с меткой времени меньшей, чем 24-12-01. Дебетовый и кредитовый обороты будут формироваться по блокам проводок с метками времени, начиная с 24-12-01 ДО блока проводок с меткой времени 25-01-01.
Функция возвращает двумерный массив данных. Индексами строк этого массива являются коды счетов. Каждой такая строка является массивом с элементами, имеющими следующие индексы:
os - входящий остаток счёта в стоимостном выражении;
on - входящий остаток счёта в натуральном выражении;
dos - дебетовый оборот счёта в стоимостном выражении;
don - дебетовый оборот счёта в натуральном выражении;
kos - кредитовый оборот счёта в стоимостном выражении;
kon - кредитовый оборот счёта в натуральном выражении.
dzaov - Агрегирование данных оборотной ведомости
Функция dzaov(dov,a) возвращает массив агрегированных данных оборотной ведомости. Параметр dov должен содержать предварительно рассчитанные данные оборотной ведомости. Параметр a определяет код атрибута описания счетов, содержащий код счёта в который агрегируются данные первичного счёта. Пример использования функции dzaov() был рассмотрен ранее.
dzvov - Вывод оборотной ведомости по счетам заданной группы
Функция dzvov(dov[,p]) оборотную ведомость по ранее сосчитанным данным массива dov в соответствии с необязательным списком параметров p. В списке p учитывается только параметр g, определяющий группу счетов, которые должны быть включены в вывод. Другие элементы списка параметров списка p используются только для вывода сведений в заголовке таблицы. Примеры использования функции dzvov() рассматривались ранее.
dzpsov - Получить столбец данных оборотной ведомости c возможной выборкой по группе счетов
Функция dzpsov(dov,st[,g]) возвращает массив значений столбца st из массива предварительно рассчитанных данных оборотной ведомости dov. Индексами массива являются коды счетов, а их значениями - значения элементов в столбце st (см. описание функции dzdov. При этом в массив включаются только данные по счетам, у которых данные в столбце st ненулевые. Если задан необязательный параметр g, то будут выбраны только данные по счетам, входящим в определяемую этим параметром группу. Примеры использования функции dzpsov рассматривались ранее.
dzvp - Вывод выборки проводок
Функция dzvp(p) осуществляет вывод проводок, удовлетворяющих условиям выборки, определяемых списком p. Этот список может включать следующие элементы:
s - счёт, участвующий в проводках как дебетуемый или кредитуемый;
ds - счёт, участвующий в проводках как дебетуемый;
ks - счёт, участвующий в проводках как кредитуемый;
a - код атрибута счёта, устанавливающий правило его агрегирования;
n - метка времени начала периода;
k - метка времени конца периода;
m - список меток, которыми должны быть помечены отбираемые проводки.
Если задан параметр s, то параметры ds, ks игнорируются. В этом случае отбираются только те проводки, в которых счёт s используется либо в качестве дебетуемого, либо в качестве кредитуемого. Если задан параметр ds, то отбираются только те проводки, в которых дебетуемым счётом является ds. Если задан параметр ks, то отбираются только те проводки, в которых кредитуемым счётом является ks. Параметры s, ds, ks могут заданы как маска счёта (первые символы). В этом случае проверяется неполное соответствие первых символов счетов проводок соответствующей маске.
Если задан параметр a, то должен быть задан только один из параметров s, ds, ks и этот счёт должен быть агрегирующим. Параметр a устанавливает код атрибута описания счетов, который устанавливает соответствие первичных счетов агрегирующим. В форму отбираются проводки, содержащие первичные счета, в описании которых в атрибуте a установлено значение s, ds, ks.
Если задан параметр n, то отбираются только те проводки, у которых установлена метка времени, НЕ меньшая, чем значение n.
Если задан параметр k, то отбираются только те проводки, у которых установлена метка времени, меньшая, чем значение k.
Если задан параметр m, то отбираются только те проводки, которые помечены метками заданными в параметре m. Если задаётся более одной метки, то их коды должны быть перечислены в параметре m через запятую без пробелов.
В форму выводятся проводки, соответствующие ВСЕМ заданным ограничениям. В подвале отчёта выводятся итоги по суммам всех отобранных проводок в стоимостном и натуральном выражении.
Примеры использования функции dzvp() рассматривались ранее.
dzdok - Формирование данных сводных оборотов по корреспонденциям первичных счетов
Функция dzdok(p) возвращает массив данных сумм всех проводок, удовлетворяющих ограничениям, заданным необязательным списком p. Список p может включать любые параметрами, но при выполнении отбора учитываются только параметры n, k, m, содержание и назначение которых уже рассматривалось ранее при описании других функций расширения.
Функция dzdok вычисляет суммы по всем проводкам для каждой уникальной корреспонденции первичных счетов. Возвращаемое значение является трёхмерным массивом. Первым индексом массива является код дебетуемого счёта, вторым - код кредитуемого счёта, третьим - значение константы 's' или 'n'. Значением элемента с третьим индексом 's' является сумма всех сумм проводок с заданной корреспонденцией счетов в стоимостном выражении. Значением элемента с третьим индексом 'n' является сумма всех сумм проводок с заданной корреспонденцией счетов в натуральном выражении.
С содержательной точки зрения функция dzdok возвращает сводные проводки по уникальным парам дебетумый-кредитуемый счета.
dzvok - Вывод данных сводных оборотов по корреспонденциям первичных счетов
Функция dzvok(sok[,p]) выводит форму, содержащую выборку сводных оборотов по корреспонденциям первичных счетов на основании ранее полученного с помощью функции dzdok массива sok. Необязательный параметр p характеризует ограничения на вывод данных. Если он не задан или пуст, то выводятся все данных массива sok. В противном случае выполняется отбор в соответствии с заданными в списке параметров значениями:
ds - дебетуемый счёт;
ks - кредитуемый счёт;
a - код атрибута счёта, устанавливающий правило его агрегирования;
Назначение и форма проявления указанных параметров аналогичны тем, которые были указаны при описании функции dzvp. Отличием является только то, что функция dzvp выводит данные по всем проводкам, а функция dzvok по их свёртке в уникальные пары корреспонденций.
dzsok - Отчёт по сводным оборотам корреспонденций счетов
Функция dzsok(p) последовательно выполняет dzdok и dzvok, выводя отчёт в соответствии с рассмотренными при описании этих функций параметрами.
Примеры использования функции dzsok(p) можно видеть как расшифровки столбцов 3 и 4 оборотной ведомости.
dzdis - Динамика изменения счёта
Функция dzdis(p) выводит данные о динамике изменения заданного счёта в соответствии с дополнительно заданными ограничениями. Параметр p является списком, кторый может включать следующие элементы:
s - счёт, участвующий в проводках как дебетуемый или кредитуемый;
a - код атрибута счёта, устанавливающий правило его агрегирования;
n - метка времени начала периода;
k - метка времени конца периода;
m - список меток, которыми должны быть помечены отбираемые проводки.
Параметр s является обязательным. На его основе отбираются только те проводки, в которых данный счёт используется либо в качестве дебетуемого, либо в качестве кредитуемого. Параметр s может задан как маска счёта (первые символы). В этом случае проверяется неполное соответствие первых символов счетов проводок соответствующей маске.
Если задан параметр a, то значение параметра s интерпретируется как агрегирующий счёт. Параметр a устанавливает код атрибута описания счетов, который устанавливает соответствие первичных счетов агрегирующим. В форму отбираются проводки, содержащие первичные счета, в описании которых в атрибуте a установлено значение s.
Если задан параметр n, то отбираются только те проводки, у которых установлена метка времени, НЕ меньшая, чем значение n.
Если задан параметр k, то отбираются только те проводки, у которых установлена метка времени, меньшая, чем значение k.
Если задан параметр m, то отбираются только те проводки, которые помечены метками заданными в параметре m. Если задаётся более одной метки, то их коды должны быть перечислены в параметре m через запятую без пробелов.
В начале формы выводится значение остатка счёта s на начало периода, заданного параметром n. Если параметр n не задан, то выводится нулевое значение. В форму выводятся проводки, соответствующие ВСЕМ заданным ограничениям. В дополнительной колонке выводится остаток счёта s после выполнения очередной проводки. В подвале отчёта выводится исходящий остаток счёта в стоимостном и натуральном выражении.
Примеры использования функции dzdis(p) можно видеть как расшифровки столбцов 2 и 5 оборотной ведомости.
dzoos - Дебетовый, кредитовый обороты за период и исходящее сальдо счёта в натуральном и стоимостном выражении
Функция dzoos(p) возвращает массив, содержащий исходящие остатки и обороты первичного или агрегированного счёта за произвольный период по проводкам с заданными метками. Функция может использоваться для формирования нестандартных отчётов, в частности, для вывода тех или иных значений, вычисленных по проводкам, в потоке текста статьи.
Список p может содержать следующие элементы:
s - счёт, участвующий в проводках как дебетуемый или кредитуемый;
a - код атрибута счёта, устанавливающий правило его агрегирования;
n - метка времени начала периода;
k - метка времени конца периода;
m - список меток, которыми должны быть помечены отбираемые проводки.
Содержание и форма интерпретации перечисленных параметров полностью аналогичны рассмотренному выше при описании других функций расширения.
Функция возвращает массив, содержащий элементы с индексами:
oss - исходящий остаток счёта в стоимостном выражении;
osn - исходящий остаток счёта в натуральном выражении;
dos - дебетовый оборот счёта в стоимостном выражении;
don - дебетовый оборот счёта в натуральном выражении;
kos - кредитовый оборот счёта в стоимостном выражении;
kon - кредитовый оборот счёта в натуральном выражении.
По сути - это строка данных оборотной ведомости, где вместо остатков на начало периода фигурируют остатки на конец периода, вычисленные при прочих ограничениях.
dzoog - Обороты и остатки всех счетов, входящих в заданные группы
Функция dzoog(p,mg) возвращает массив содержащий исходящие остатки и обороты счетов для всех счетов, входящих в группы, перечисленные в списке mg. Реализуется как последовательность вызовов функции dzoos для каждого счёта, входящего перечень групп mg. Возвращает двумерный массив, индексами строк которого являются коды счетов, а индексы столбцов в точности совпадают с индексами, рассмотренными при описании функции dzoos.
dzoot - Текущие исходящие остатки и обороты первичного счёта
Функция dzoot(s[,m]) возвращает массив, содержащий текущие исходящие остатки и обороты первичного или агрегированного счёта по проводкам с заданными метками. Вычисления производятся строго ДО текущего внутреннего номера проводки. Функция может использоваться ТОЛЬКО при реализации спецалгоритмов автоматического формирования проводок. Список меток необязателен. Примеры использования функции рассмотрены ранее, в разделе статьи, посвященном спецалгоритмам.
dztok Текущий оборот по корреспонденции счетов
Функция dztok(ds,ks,m) возвращает массив из двух элементов. Элемент с индексом 0 содержит текущий оборот с кредита первичного счёта ks в дебет первичного счёта ds в стоимостном выражении, а элемент с индексом 1 - в натуральном выражении. Если задан необязательный параметр m, то вычисления производятся только по проводкам, содержащим все метки, перечисленные в этом параметре через запятую. Вычисления производятся строго ДО текущего внутреннего номера проводки. Функция может использоваться ТОЛЬКО при реализации спецалгоритмов автоматического формирования проводок.
dzoks - Суммарный оборот по нескольким корреспонденциям счетов
Функция dzoks(p) возвращает массив из двух элементов. Элемент с индексом 0 содержит совокупный оборот с кредита заданных первичных счётов в дебет заданных первичных счётов в стоимостном выражении, а элемент с индексом 1 - в натуральном выражении. Параметр p задаёт список ограничений, используеммых при вычислениях, и может включать следующие элементы:
ds - маска дебетуемого счёта;
ks - маска кредитуемого счёта;
gd - группа дебетуемых счетов;
gk - группа кредитуемых счетов;
n - метка времени начала периода;
k - метка времени конца периода;
m - список меток, которыми должны быть помечены обрабатываемые проводки.
Вычисления производятся по следующим правилам. Если проводка удовлетворяем заданным ограничениям на метки времени n и k, содержит метки, определяемые элементом m, дебетуемый счёт входит в группу gd и/или соответствует заданной маске ds, а кредитуемый счёт входит в группу gk и/или соответствует заданной маске ks, то её суммы в стоимостном и натуральном выражении прибавляются к соответствующим элементам результатного массива.
dzopsa - Отладочный вывод для спецалгоритмов
Функция dzopsa(k) используется для вывода массива проводок и массива счетов, сформированных до текущего момента в спецалгоритмах. Если параметр k нулевой, то выводятся описания счетов, если k=1 (значение по умолчанию), то выводится массив проводок.