История создания технологии

Вячеслав Черников,

разработчик программы Финсофт:КупецЪ.

В этой статье описывается история разработки программы ФинСофт:КупецЪ и лежащей в ее основе технологии.


Причины начала разработки

Создание технологии, на которой базируется программа ФинСофт:КупецЪ, было начато в 2003 году. К тому времени я оставил наемную работу в банковском секторе и в течении 5 лет занимался автоматизацией учета на различных предприятиях г.Рязани, используя в качестве средства разработки программу 1С-Предприятие 7.7.

Просто так сложилось. В 1998 году один знакомый предприниматель попросил наладить учет в своей фирме, торговавшей оптом хозяйственными товарами. В банке я программировал под Dos, времени для перехода на Windows было мало, а порог вхождения в 1С-Предприятие оказался достаточно низок. Кроме того, большинство организаций к тому времени уже работали на этой платформе. К 2003 году я систематизировал все наработки на 1С в виде конфигурации ФинСофт:Бухгалтерия, целиком построенной на бухгалтерской компоненте. Из старых проектов осталась только программа ФинСофт:Зарплата, переведенная с Dos на Windows. Программы обменивались итоговыми проводками, поэтому пакет достаточно полно покрывал потребности бухгалтерий небольших предприятий.

В 2003 году встал вопрос, куда двигаться дальше. Работа с 1С имела ряд недостатков.

1. Все, что разрабатывалось, называлось 1С-Предприятие, свой собственный брэнд отсутствовал. Хотя продукт этой московской фирмы использовался только как инструмент разработки.

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

3. Наличие платформы позволяло быстро вносить изменения в конфигурации прямо на рабочем месте клиента. С другой стороны, это приводило к сильной индивидуализации решений. Когда количество клиентов превышало определенный предел, нагрузка на поддержание работающих решений чрезмерно возрастала.

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

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


Почему Clarion?

Для начала разработки требовалось подобрать инструмент, который бы позволял создавать программы с такой-же эффективностью, как в 1С-Предприятие, но лишенный недостатков этой платформы.

До 1998 года я разработал много разных программ на Clarion 2.1 под операционную систему Dos - популярной системе в первой половине 90-х годов. Все эти программы постепенно ушли в историю, кроме проекта ФинСофт:Зарплата, который в 1999 году был переведен на Clarion 5 для Windows. Позже я лицензировал Clarion специально для этого проекта.

Clarion имел ряд привлекательных сторон по сравнению с 1С-Предприятие и решал описанные выше проблемы.

1. Система была ориентирована на независимых разработчиков программного обеспечения. Лицензировав Clarion в профессиональной редакции (примерная стоимость составляла 800 долларов), разработчик получал все права на создаваемые с его помощью программные продукты без каких-либо дополнительных отчислений.

2. Создаваемые программы не требовали никаких дополнительных компонентов для установки и поддержки у пользователя (кроме, конечно, операционной системы Windows).

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

4. Clarion позволяет вести проект на уровне метаданных, как и 1С-Предприятие.

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

6. Программы на Clarion компилируются в машинный код и работают очень быстро.


Функции общего назначения

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

Поэтому в начале разработки была создана библиотека базовых функций fslibs6.dll. Эта библиотека содержит более 100 функций (работа со строками, датами, форматирование, некоторые базовые диалоги)

и наращивается по мере необходимости. Все прикладные модули знают эти функции и могут использовать простыми вызовами. Например, следующие две функции выполняют примерно одинаковые действия:

1С: Предупреждение("Это предупреждение");

FinSoft: FsMessagePr('Это предупреждение')

Вот так выглядит дерево процедур библиотеки в среде clarion:

Для сравнения скриншот из 1С-Предприятие 7.7:


Система метаданных

В Clarion, как и в 1С-Предприятие, проекты ведутся на уровне метаданных, то есть в специализированных базах данных. Главное отличие составляет то, что метаданные 1С-Предприятие (конфигурации) обрабатываются с помощью специальной программы (платформы), устанавливаемой непосредственно у конечного пользователя. Метаданные Clarion (шаблоны) используются для генерации исходных текстов программ на языке Clarion с последующей их компиляцией в машинный код. Пользователю передается готовая программа.

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

В Clarion существуют две основные линейки шаблонов: классические (процедурные) и ABC (объектные). Я остановил свой выбор на классических. С 1С-Предприятие их роднит подход - в языке программирования используются встроенные объекты, а прикладной код пишется в процедурном стиле. Хотя сам язык Clarion поддерживает объектное программирование, в отличии от языка 1С-Предприятие.

В 1С-Предприятие объекты метаданных хорошо проработаны и заранее предопределены. В Clarion мне пришлось проделать большую работу по расширению набора объектов, так как базовый набор не давал необходимого функционала. Сейчас эта библиотека содержит около 150 специализированных шаблонов различного назначения.

Метаданные в 1С хранятся в одном файле 1сv7.md:

В Clarion структура данных описывается в словаре (dct), процедуры в аппликациях (app). App-файлов, работающих с одним словарем, может быть много. При их компиляции можно создавать как исполняемые программы (exe), так и динамические windows-библиотеки (dll). Это обеспечивает модульную архитектуру проекта.

Так выглядит словарь в Clarion:

Так выглядит app-модуль:


Форматы хранения данных

Работая с 1С-Предприятие 7.7, я использовал встроенный формат хранения данных dbf. Приложения обычно работали на терминальных серверах. Поскольку клиентами были небольшие предприятия, специализированная СУБД MS SQL не использовалась.

В Clarion можно работать как со встроенными форматами баз данных, так и с различными СУБД. Основным встроенным форматом является патентованный topspeed-формат (tps), который используют большинство разработчиков на Clarion. На нем я и остановил свой выбор.

Работа с Topspeed похожа на работу с dbf. Кроме этого, обнаружился ряд преимуществ.

1. Topspeed имеет встроенную шифрацию, что важно с точки зрения защиты информации.

2. Topspeed имеет записи переменной длины и автокомпрессию. Это позволяет, в частности, не заботиться о длине текстовых полей.

3. В Topspeed используется внутренняя система верификации ошибок в файле базы данных.

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

5. Транзакции выполняются очень быстро - сначала изменения накапливаются в оперативной памяти, а затем единым пакетом записываются в базу данных.

6. Очень высокая скорость чтения данных по первичному ключу, что важно для построения итерактивных программ.

С Topspeed не рекомендуется работать в старом файл-серверном режиме. Автокомпрессия и расположение индексов в одном физическом файле с данными определяют дополнительные риски повреждения при различных сетевых сбоях. Поэтому основной рабочей лошадкой остались терминальные сервера.

Дополнительно были разработаны методики сборки программ для работы с форматом Topspeed в клиент-серверном режиме (с управлением по ip-протоколу) и для работы с известной коммерческой базой данных pervasive для возможных крупных клиентов (более 50-60 рабочих мест). Обе эти сборки полностью совместимы по коду со стандартным вариантом. Чтобы получить альтернативную сборку, достаточно включить нужную опцию в параметрах словаря и пересобрать проект.

Был также полностью автоматизирован процесс преобразования базы данных из формата topspeed в btrieve (первасив) и обратно.


Изменение структуры данных

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

В 1С-Предприятие в конфигураторе выполняется загрузка измененной конфигурации, затем программа сверяет новую структуру с имеющейся (описанной в файле 1cv77.dd для варианта с dbf-форматом хранения) и, при нахождении изменений, переливает содержимое из файла со старой структурой во временный файл с новой структурой, а затем делает замещение.

У разработчиков на Clarion для этих целей имелись два инструмента. Зарубежные разработчики обычно используют FM (файл-менеджер), разработанный фирмой CapeSoft из ЮАР, русскоязычные DC (дата конвертор), разработанный украинским программистом Вадимом Синявским. Инструменты имеют разные подходы для автоматизации изменения структуры базы данных. Вначале я хотел приобрести DC, но в ходе переписки с разработчиком сложилось впечатление, что он не особо заинтересован в развитии и продвижении своего инструмента из-за малой потенциальной клиентской базы. Кроме этого, DC, судя по описанию, тянул информацию о версиях структуры вместе с приложением, мне же хотелось иметь простой конвертор без дополнительных усложнений. После некоторых раздумий было принято решение разработать свой. Все удалось реализовать с помощью языка шаблонов Clarion. Были разработаны два шаблона. Первый генерит файл версий структуры таблиц базы данных, сопоставляя содержимое этого файла и текущую структуру таблиц в словаре. Файл версий - это обычный текстовый файл, в который заносятся декларации таблиц. При первой генерации записываются декларации всех таблиц, затем только тех, структуры которых изменились. Версии разделяются специальной строкой-разделителем с номером. В конец строк деклараций дописываются внутренние идентификаторы таблиц, полей и ключей (индексов), как они определены в словаре. Файл версий выглядит следующим образом:

Второй шаблон обрабатывает файл версий и генерит текст процедур конвертации, который затем компилируется в исполняемую программу. Работа конвертора аналогична работе в 1С - содержимое таблицы старого формата переливается во временную таблицу нового формата, затем происходит замещение. Чтобы определить текущую версию формата таблицы, программа последовательно пытается открыть ее в цепочке процедур конвертации. Когда открытие выполняется без ошибки, считается, что это текущая версия. Далее происходит подъем версии до последней.

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

В результате разработка конвертора стала занимать буквально несколько секунд. У клиента достаточно просто запустить программу-конвертор на выполнение. Получилось даже проще, чем в 1С.

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


Модульная архитектура

Вначале я пробовал делать программы, состоящие из одного исполняемого exe-модуля. Но по мере роста функционала переключился на модульную архитектуру.

Сейчас ФинСофт:КупецЪ является модульным приложением, в котором весь прикладной и системный функционал располагается в dll-модулях (всего их около 20), а запускающий exe-модуль содержит только набор типовых фреймов (главных меню).

Часть dll-модулей входят в ядро системы и поставляются всем пользователям. Для некоторых dll имеются заглушки - dll-модули с теми же именами и прототипами функций, но вместо самих функций содержащие вывод сообщения или просто завершение работы. Это нужно для того, чтобы уменьшить размер приложения для пользователей, не использующих имеющийся в них функционал. Например, модуль "Производство" не требуется для торговых предприятий, его можно заменить небольшой (около 50кб) заглушкой. Еще часть dll-модулей содержат библиотеки отчетов и обработок и динамически подгружаются по мере необходимости.

Переход к модульной архитектуре, с одной стороны, уменьшил время на кодогенерацию и компиляцию, а с другой позволил плавно наращивать функционал объемной комплексной системы.


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

Среда clarion позволяет легко создавать стандартные модульные Windows-приложения, но не имеет средств для эффективной работы с набором app-модулей. Поэтому было разработано специальное приложение для внутреннего использования ФинСофт:Ассистент. В этом приложении был подключен функционал, облегчающий работу со средой clarion. В процессе генерации кода средой Clarion в специальные ресурсные файлы записывается информация, которая затем загружается во внутреннюю базу данных ФинСофт:Ассистент.

ФинСофт:Ассистент обеспечивает следующие основные функции.

1. Удобный просмотр структуры базы данных и генерация типовых конструкций для вставки в редактор clarion.

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

3. Кодогенерация и компиляция всех или выбранных модулей.

4. Библиотека макросов (типовых образцов кода) для вставки в редактор clarion.

5. Просмотр функций стандартной библиотеки, классов, глобальных переменных, пиктограмм, меток, шаблонов с возможностью поиска, выбора и вставки в среде clarion.

6. Сбор статистики проекта.

7. Система фиксации и контроля версий.

Вот так выглядит основное меню ФинСофт:Ассистент:


Защита данных

Одной из важных особенностей встроенной файловой базы данных topspeed является шифрация данных. Чтобы получить доступ к данным, программа должна вначале получить ключ - некоторое строковое значение (пароль). Причем разные таблицы базы данных могут быть зашифрованы разными ключами.

Чтобы защититься от кражи данных, в Купце используются два ключа на разные наборы таблиц. Эти ключи могут быть размещены в любом месте локальной сети, в том числе на сменных носителях. Пользователь имеет возможность установить свои значения ключей, программа обеспечивает автоматическую перешифрацию данных.

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

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


Аудит данных

Большой проблемой при работе с 1С-Предприятие 7.7 было отсутствие возможности контроля изменений в базе данных. В 1С-Предприятие 8 ввели такую функцию, но только для отдельных конфигураций. Видимо, разработчики опасаются ухудшения производительности системы. Кроме того, сложно вести протоколирование изменений в базе данных, структура которой создается автоматически из метаданных и часто меняется.

Когда я приступил к разработке технологии, вопрос аудита данных был приоритетным. Это значит, что аудит появился в Купце с первых версий.

Для ведения лога изменений данных была выбрана компактная форма, при которой в специальную системную таблицу записывается минимум информации. При добавлении записи сохраняются только значения заполненных полей, при изменении записи сохраняются только новые значения полей, при удаленнии записи сохраняется только ее внутренний идентификатор. Такой лог был назван транзакционным. При создании резервной копии базы данных содержимое лога переливается в дополнительную архивную таблицу. Это позволяет держать основную модифицируемую таблицу лога с минимальным объемом информации. Среда разработки автоматически генерит с помощью специальных шаблонов слой функций для работы с таблицами базы данных, в котором закладывается поддержка лога. Таким образом, поддержка лога практически не требует ручного кодирования.

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

Так выглядит стандартный диалог работы с логом изменений.

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

Для складских документов можно сравнить изменения в строковой части между двумя моментами фиксации, а также восстановить версию накладной на заданный момент фиксации.


Работа с итогами

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

Мне с самого начала хотелось принципиально уйти от использования механизма проведения документов. Все отчеты в Купце строятся на основании содержимого документов, в понимании 1С регистры отсутствуют. Чтобы не обрабатывать в расчетах все документы, были введены документы остатков, которые закрывают период. Программа определяет ближайшие к запрошенному в отчете периоду остатки и выполняет все расчеты от них. Программа также запрещает изменения документов в закрытом периоде. Если такое потребуется, то остатки могут быть выключены, а после изменений актуализированы. Останавливать работу других пользователей с программой при этом не надо. Периодичность создания документов остатков произвольная, обычно месяц.

Для оптимизации производительности работы программы было введено сохранение сводных оборотов в закрытых периодах в некоторых разрезах. Период оборотов определяется двумя граничными документами остатков. При формировании ресурсоемких отчетов программа разбивает период отчета на подпериоды и, если имеются сводные обороты, использует их, не обрабатывая документы. Затем итоги подпериодов объединяются.

Можно заметить, что структура регистров в 1С-Предприятие напоминает таблицы остатков и оборотов в Купце. Но в Купце эти таблицы гораздо компактнее и не обновляются при сохранении документов.

Так выглядит журнал документов остатков.

Так выглядит журнал документов оборотов.

Так выглядит документ остатков.

Так выглядит документ оборотов.


Интерфейс

Одной из самых сильных сторон программы 1С-Предприятие всегда являлся интерфейс. Как я заметил, зарубежные разработчики придают различным наворотам в интерфейсе меньшее значения, акцентируя внимание на скорости и стабильности работы программ. Тем не менее, в Clarion интерфейс был хорошо продуман, доделать пришлось некоторые дополнительные надстройки.


Панель переключения потоков

В 1С-Предприятие используется многооконный MDI-интерфейс с возможностью быстрого переключения открытых потоков через закладки. В типовом интерфейсе программ на Clarion также используется MDI-интерфейс, но панель переключения потоков отсутствует. Точнее, ее реализация появилась позже в Clarion7. Существенным отличием MDI-интерфейса в Clarion является тот факт, что каждый поток соответствует нативному Windows-потоку. В 1С-Предприятие используется внутренняя реализация менеджера потоков, как это было в Clarion более ранних версий. Использование нативных Windows-потоков дает ряд преимуществ. Например, в Купце можно запустить отчет на формирование в одном потоке, а в другом вводить накладную. Можно интегрироваться с внешними компонентами и библиотеками, которые ничего не знают про внутреннюю кухню нашей программы, но хорошо знают о Windows-потоках. Оптимальнее работает программа на многоядерных процессорах, так как обработка потоков может быть разнесена по разным ядрам.

Реализовывать панель переключения потоков пришлось самостоятельно. Чтобы далеко не уходить от стандартных возможностей языка Clarion, панель была реализована в вертикальном виде, что отличает ее от горизонтальной панели в 1С.

Вот так выглядит типичный диалог в 1С-Предприятие:

Вот так выглядит диалог в программе ФинСофт:КупецЪ:

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

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


Списки

В версии 1С-Предприятие 7.7 работа со списками достаточно примитивна. Значительные улучшения были сделаны в 1С-Предприятие 8. В программе ФинСофт:КупецЪ работа со списками менее навороченная, чем в 1С-Предприятие 8, но имеет все необходимые функциональные возможности.

Начнем с переключения порядка сортировки. В Clarion стандартно для этой цели использовались закладки. Я оставил этот вариант, так как он выглядит вполне наглядным и удобным.

Обычно закладки используются для переключения порядка сортировки в справочниках. В журналах документов закладки используются для изменения индексируемых отборов. Я разработал дополнительный шаблон, позволяющий активировать кнопку выбора граничных условий.

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

В режиме поколончатой подсветки (переключается кнопкой с желтым кружком под правым нижним углом списка) работает также поколончатый поиск. Аналогично, как в 1С-Предприятие 7.7, был введен механизм копирования значения из подсвеченной колонки (Ctrl+C) с последующей вставкой в поле поиска (Ctrl+V).

Реализация фильтра была сделана упрощенной. Нужно щелкнуть правой кнопкой мышки по заголовку колонки, программа запросит образец для отбора записей. Для строки это подстрока, для числа или даты это граничные значения.

Такие условия можно задать по каждой колонке. Часто используемые условия отбора можно сохранить в списке "Избранное", а затем выбирать по мере надобности.

Чаще фильтры делают более навороченными, позволяя вводить различные условия сравнения и формулы. Но мне показалось, что можно оставить упрощенный вариант. Он удобнее. Кроме этого, использование фильтра не такая частая функция, так как работает медленно. Поэтому фильтр обычно применяют в комбинации с ограничениями по индексам. В Купце также не сохраняется история отборов, как это сделано в 1С-Предприятие 8.

Еще одна удобная возможность при работе со списками в Купце - при щелчке мышкой по заголовку колонки при нажатой клавише Shift выводится на просмотр информация из связанного справочника или выполняется подсчет итога значения в колонке для всех строк списка.

В Купце можно скрывать отдельные колонки, но нельзя менять их местами, как в 1С-Предприятие 8. Дело в том, что колонки могут изменяться в зависимости от параметрических настроек программы, и мне не хотелось усложнять управление этим процессом. Кроме того, важно придерживаться правила, чтобы внешний вид диалогов был максимально стандартизирован, иначе усложнится работа техподдержки (наш сотрудник видит одно содержимое экрана, а пользователь другое). По этой же причине я не стал вводить возможность динамического изменения положения и вида контролов окон, как сделано в некоторых известных системах.


Поля ввода

В 1С-Предприятие поля ввода цифр и дат сопровождаются специальными кнопками калькулятора и календаря. Довольно удобно, поэтому я перенял эту возможность. Подключить кнопки несколько дольше, чем в 1С. Вначале создается поле ввода, затем к нему прикрепляется шаблон кнопки. В работе функционал перекрывается полностью.

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

Если ссылка делается на справочник без кода или на документ, то выбор похож на реализацию в 1С.

Горячая клавиша F4 используется для выбора значения из справочника с помощью клавиатуры, когда активно поле ввода кода. Нажатие комбинации клавиш Shift+F4 позволяет открыть на просмотр форму элемента справочника, но в Купце эта возможность не задействована.

Для длинных строковых полей в Купце подключается выбор из списка типовых текстов, а при нажатии комбинации клавиш Shift+F4 вызывается диалог расширенного ввода (аналогично, как сделано в среде Clarion).


Навигация между диалогами

В Купце реализованы навигация сверху вниз (отчет - детализирующий отчет - первичный документ) и навигация снизу вверх (документ - отчет по контексту).

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


Ввод документов на основании

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


Работа с отчетами

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

В Clarion подобного инструмента нет. Поэтому для реализации нужного функционала были использованы три разные методики.

Если нужно сформировать отчет, а затем с ним работать (вызывать связанные отчеты, вводить данные и т.п.), то используется стандартный для Clarion броуз - табличный вывод строк. При этом диалог делится на две закладки (иногда больше), на первой из которых вводятся исходные параметры, на второй выводятся итоги. Броуз может быть автоматически распечатан или сохранен в Excel-формате в том виде, как на экране.

Печатные формы первичных документов готовятся с помощью специального встроенного генератора отчетов FRB. Это единственная коммерческая библиотека, которая используется в Купце (кроме собственно Clarion). FRB имеет ряд недостатков, в частности проблемы с автоматическим переносом длинных строк, но и дает ряд преимуществ - возможность создавать бланки непосредственно в программе и делать вывод в редактируемый RTF-формат. Я разделил все печатные формы на 3 группы - стандартные, дополнительные и пользовательские. Пользователи могут перекрыть любой стандартный бланк своим, а также разработать дополнительные бланки. Вот так выглядит редактор печатных форм FRB.

Наконец, для заказных отчетов, в которых достаточно сформировать табличную форму с итогами в определенном виде, используется библиотека прямого вывода в Excel. Эти отчеты пишут результат напрямую в файл формата Excel 4, который затем может быть открыт с помощью Excel или OpenOffice. Для записи используется специальный класс, разработанный московским программистом Олегом Руденко и выложенный им в бесплатный общий доступ. Для отрисовки бланка я использую Excel. Excel-бланк препарируется специальной обработкой, которая через механизм OLE по заданным координатам секций считывает информацию и сохраняет в специальном файле разметки. Затем уже этот файл разметки используется при выводе отчетов. Код формирования отчета практически идентичен коду в 1С. Бланк в Excel выглядит следующим образом.

Файл разметки выглядит так.

Код формирования отчета выглядит так.


Графики

Возможность просмотра итогов в графическом представлении некоторым пользователям очень нравится. Особенно, когда можно быстро переключиться из стандартного табличного представления в графическое.

В языке Clarion всегда были примитивные функции для построения графиков, но не было специализированного инструмента. Он появился позже в версии Clarion 6 как библиотека, которую можно приобрести отдельно. Когда я начинал разработку технологии, в готовом виде была доступна только коммерческая библиотека от третьей фирмы CapeSoft из ЮАР. Я также нашел пару незавершенных опенсоурс проектов и решил сделать свою библиотеку на их основе. Так появились класс для построения графиков и шаблон для его использования. Вот как выглядят графики в Купце.

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


Отладка программ

Важной составляющей любой среды разработки является отладчик.

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

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

Вот так выглядит отладчик в 1С-Предприятие 7.7.

Вот так выглядит отладчик в Clarion.

Несмотря на принятые усилия (объединение переменных в группы для облегчения поиска, методика вызова отладчика из нужного места программы), мне так и не удалось наладить эффективную работу с ним. Надо заметить, что большинство разработчиков на Clarion отладчиком не пользуются. Значительная часть кода программы генерится шаблонами и не требует отладки. В ручном коде обычно используют операторы stop или message, выводящие сообщения во время выполнения программы. Некоторые приспособились выводить и просматривать windows-сообщения с помощью известной программы DbgView.

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

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

Свой отладчик я сделал достаточно быстро - в течении 3 или 4 дней. Видимо, на тот момент в голове уже сложилась четкая картинка, как что организовать. Позже отладчик (назовем его ФинСофт:Отладчик) еще доводился до кондиции в течении некоторого времени.

Идея была очень простой. Проект ведется в специальной базе (метаданных), на основании содержимого которой генерятся исходные тексты программ и компилируются в исполняемые файлы или библиотеки. Мы вклиниваемся после генерации исходных текстов и вставляем через строку кода вызов диалога своего отладчика. Предварительно собираем ссылки на локальные и глобальные переменные во внутренних структурах специального интерфейсного класса, адрес которого передаем при вызове отладчика. Чтобы уменьшить накладные расходы при выполнении программы, вызовы вставляются только в локализованный фрагмент исходного кода, работу которого нужно проверить. В clarion фрагменты кода принято оформлять в виде так называемых рутинок (routine), поэтому я привязал отладку к ним. Далее управление вставкой отладочных вызовов было полностью интегрировано в программу ФинСофт:Ассистент. Теперь покажу, как это работает.

Ссылки на локальные переменные мы можем подключить по их декларациям в отлаживаемой процедуре. Для подключения ссылок на глобальные переменные (группы переменных и массивы в памяти) я разработал небольшой шаблон, который вставляет в исходные тексты специально оформленные комментарии. По этим комментариям парсер текста в ФинСофт:Ассистент определяет имена внешних по отношению к процедуре глобальных переменных.

Шаблон выглядит следующим образом.

Вот так выглядит результат работы шаблона в исходных текстах.

Далее, в программе ФинСофт:Ассистент находим нужную процедуру и отмечаем рутинки, которые хотим отладить.

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

Вот так выглядит фрагмент отлаживаемого кода.

Далее исходный текст компилируется, программа запускается на выполнение. Когда мы доходим до нужного фрагмента кода, вызывается диалог отладчика. Вот так выглядит процесс отладки.

Поскольку код отладчика полностью контролируется, мы можем подключить все необходимые функции. ФинСофт:Отладчик позволяет выполнять фрагмент кода пошагово, устанавливать простые и условные точки прерывания, просматривать значения переменных, групп переменных, массивов данных в памяти (в clarion они называются queue - очереди), результаты динамически вводимых выражений, устанавливать значения переменных и т.д.

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

Чтобы отключить отладчик, достаточно восстановить исходный текст из копии (это делается щелчком мышки в ФинСофт:Ассистент) или перегенерить текст, внеся изменения в процедуру в среде Clarion.

В целом полученный результат меня устроил. Теперь отлаживать сложные расчеты стало действительно просто и комфортно.


Автотестирование

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

В 1С-Предприятие есть стандартная функция тестирования и исправления базы данных.

Работает она медленно. Сказывается, видимо, большое количество внутренних взаимосвязей между таблицами системы. Медленно работает функция проверки недопустимых символов в строковых полях.

Другое средство автотестирования - проверка корректности ведения учета, которое делают для стандартных конфигураций.

В Купце функции автотестирования всегда были в фокусе внимания. Вот так выглядит диалог тестирования базы данных.

Исправление ошибок здесь не требуется, так как в базе нет вторичных данных и минимальное количество внутренних зависимостей. От проверки корректности ввода символьных строк я отказался, так как проблема может проявиться только в процессе обмена с другими программами и там же локализуется. Чаще всего достаточно выполнить проверку контрольных сумм и оперативных остатков. Проверка целостности базы данных занимает гораздо больше времени и выполняется реже, так как физические проблемы хранения данных хорошо диагностируются драйвером topspeed в процессе работы, а логические ошибки минимизированы с помощью интерфейса. В целом тестирование базы данных работает намного быстрее, чем в 1С-Предприятие, и не требует останова работы других пользователей. Нужно еще отметить, что процедура проверки логической целостности базы данных генерится полностью автоматически на основании содержимого словаря.

В Купце имеется функция автотестирования бизнес-логики.

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

Некоторые проверки разрабатываемого проекта можно сделать в среде Clarion. Специальные шаблоны проверяют правила оформления деклараций таблиц в словаре и процедур в модулях.

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


Прикладные алгоритмы

Здесь описаны наиболее интересные прикладные алгоритмы.


Парционный учет товаров

В Купце учет движения товаров на складе ведется по методу ФИФО. Остатки товаров хранятся в разрезе приходных накладных, списание реализовано в хронологическом порядке. Я не стал включать в проект поддержку учета по среднескладским ценам, чтобы не усложнять интерфейс. ФИФО дает всю необходимую информацию, в то время как при использовании среднескладских цен могут возникнуть проблемы. Например, до недавнего времени для принятия к учету затрат на приобретение сырья при упрощенной системе налогообложения требовалось отслеживать факты оплаты сырья поставщику и списания его в производство одновременно. Затем это отменили, но мы не можем знать, что придумают чиновники завтра, и должны быть максимально готовы к любым неожиданностям.

Отличительной особенностью парционного учета по методу ФИФО в Купце является то, что программа выполняет распределение отгрузок (списаний, перемещений) по приходам динамически в процессе формирования отчетов. И лишь по мере закрытия периодов в базе данных сохраняется сводная информация, необходимая для оптимизации скорости расчетов. Вот как выглядит карточка товара.

На скриншоте в верхнем списке показаны итоги в разрезе приходных накладных, в нижнем детализация движения по документам.

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

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

Надо еще отметить, что порядком списания по ФИФО можно управлять. Например, если используется учет по сделкам, то движение отдельных товаров можно привязывать к ним. В этом случае списание товаров будет выполняться только с приходов, относящихся к той же сделке. В фискальном учете в ряде случаев списания можно явно привязывать к приходным накладным, списание по некоторым приходным накладным начинать с заданной даты.


Подокументный учет оплат

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

Долгое время в Купце поддерживалось только автоматическое перекрытие документов. Мне не хотелось вводить явные отметки, какой долговой документ каким платежным документом оплачен, так как это чревато ошибками для пользователей. Но затем все же ручные отметки были введены в отношении многие-ко многим. Ручные отметки можно использовать, но они не обязательны. Не связанные ручными отметками документы программа обрабатывает, как было описано выше. Полность проконтролировать возможные ошибки пользователей в процессе ввода информации при использовании ручных отметок оплат довольно проблематично. Поэтому я добавил специальный контрольный отчет "Контроль ручного распределения оплат".

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


Учет возвратов

Когда покупатель возвращает товары, нужно определить документы, по которым они отгружались. Купец не требует от пользователя искать отгрузки самостоятельно, а берет эту работу на себя. При этом учитывается, что в одной возвратной накладной могут быть указаны товары, отгружавшиеся в разное время, отгружавшиеся по нескольким накладным. Программа также учтет предыдущие возвраты, чтобы один и тот-же товар не возвращали повторно. Идентификация возвращаемого товара осуществляется по трем признакам: продавец, покупатель, цена продажи. Для возвратной накладной разработана специальная форма, в которой возвращаемые товары сгруппированы по отгрузкам. Если отгрузка не найдена, то товары объединяются в фиктивную отгрузочную накладную.

Специальный отчет позволяет проконтролировать возвраты за заданный период времени.


Учет затрат

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

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

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

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

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

Учет затрат, которые принимаются к учету пропорционально выручке, ведется при формировании книги доходов и расходов. Непосредственно в книгу такие затраты включаются в части опта одной строкой за каждый отчетный период. К книге прилагается специальный реестр за каждый отчетный период, в котором выводятся все документы с пропорционально разделяемыми затратами, указывается выручка по опту и рознице нарастающим итогом с начала года, сумма затрат, принятых к учету в предыдущие периоды и сумма затрат, принимаемая к учету в отчетном периоде, пересчитанная нарастающим итогом.

Конечно, отдельные виды затрат можно сразу отнести к опту или рознице, если для этого имеются соответствующие основания.


Зарплата

Я долго думал, стоит ли делать из Купца комплексное решение. Чем больше функционал программы, тем сложнее ее поддерживать и продвигать через интернет. Но пожелания пользователей постоянно подталкивали на расширение функционала.

Я занимаюсь зарплатной тематикой долгое время, начиная с 1992 года, когда была разработана специализированная программа для расчета заработной платы. В 1999 году эта программа была переведена с Dos на Windows и используется в ряде организаций до сих пор.

Включение зарплатного функционала в проект ФинСофт:КупецЪ позволяло организовать единый документооборот, а также уйти от поддержки дополнительного проекта. Я сделал ревизию использованных в автономной программе методик, и в составе Купца был разработан модуль для расчета зарплаты. Этот модуль может использоваться как в составе единой комплексной системы, так и в качестве отдельного инструмента. Новое решение в значительной мере сохранило прежние методику работы расчетчиков, методику настройки и отладки расчета начислений и удержаний. Добавилось несколько принципиальных возможностей: мультифирменный учет в одной базе данных, многопользовательская работа, защита информации, удобный многооконный интерфейс. Обработка специфичных документов (больничных, отпусков и т.п.) была убрана в код, в старой программе для них использовался скриптовый язык настройки. Я также ушел от использования скриптового языка при формировании отчетов. Вот так выглядит диалог работы с начислениями и удержаниями выбранного работника.


Бухгалтерский учет

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

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

Так выглядят проводки по документу.

Так выглядит стандартный отчет "Анализ счета".

Первоначально вызывал опасения вопрос, насколько будет адекватна скорость формирования бухгалтерских отчетов при описанном подходе. Практика показала, что львиную долю времени занимает расчет себестоимости товаров при списании по методу ФИФО , особенно, если открыт для изменений большой период (несколько месяцев). С другой стороны, бухгалтера не так часто правят товарные накладные, в основном подгоняют затраты, разносят начисления и оплату налогов и т.п. Поэтому я ввел технологию кэширования расчета себестоимости товарных документов. Кэш создается для каждого бухгалтера. Актуальность итогов в кэше проверяется по логу. Если товарные документы не менялись со времени предыдущего расчета, то программа использует сохраненные результаты, если менялись, то расчет будет выполнен повторно и его результаты снова сохранятся в кэше. Введение технологии кэширования позволило значительно поднять время отклика системы - если товарные документы не менялись, то скорость построения отчетов находится в пределах нескольких секунд.


Производство

Обычно торговые системы тесно сплетаются с производственными. Вначале проект ФинСофт:КупецЪ был ориентирован на предприятия оптово-розничной торговли. Затем появились запросы на подключение производственного функционала.

Я давно работаю с производственными предприятиями. Где-то с 1992 года, когда была разработана первая программа калькуляции себестоимости готовой продукции для одной из швейных фабрик, еще на CDP 2.1. Поэтому тема была не нова.

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

Позже из старой программы ФинСофт:Бухгалтерия было перенесено многопередельное швейное производство. Появился производственный контур, была разработана система интеграции производственной и торговой подсистем. Списание сырья и материалов со склада в производство трактуется как приход в цех. Учет в цехах ведется по среднескладским ценам. Были разработаны основные производственные документы - разделка, сборка, перемещение между участками обработки, выпуск готовой продукции, фактическая калькуляция себестоимости.

Затем появился клиент, производящий натяжные потолки. В Купце была добавлена поддержка позаказного производства.

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

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


Фискальный учет

Основная клиентская база проекта ФинСофт:КупецЪ состоит из индивидуальных предпринимателей. Фискальный учет для них менее формализирован по сравнению с юридическими лицами. Для небольших предприятий оказалось целесообразно иметь возможность вести свой внутренний оперативный учет и фискальный учет в единой базе данных. В этом случае не нужно приобретать дополнительное программное обеспечение, организовывать выгрузку и загрузку информации. Более крупные используют две копии Купца, в одной ведут оперативный учет, в другой фискальный. Для предпринимателей автоматизирован учет НДС (включая разные ставки, возвраты, предоплаты, два вида деятельности (опт и розница)), формирование книги учета доходов и расходов по разным системам учета (традиционная, упрощенка доходы и расходы, упрощенка доходы).

Вот так выглядит список фискальных отчетов:


Что дальше?

С начала разработки проекта ФинСофт:КупецЪ прошло более 7 лет. За это время он был неплохо оттестирован на практике и стал серьезным комплексным решением, включающим более 1300 диалоговых окон и более 200 таблиц в базе данных. Подтянулась документация, написан ряд статей. Созданная технология позволяет быстро отрабатывать запросы клиентов. Но главное, что при всех своих функциональных возможностях, система продолжает работать очень надежно, быстро и без проблем.

Какая судьба ждет проект, покажет время.