Fabula (jFabula)

Клиентское web-приложение оперативного учёта: заказы, задачи, платежи, контрагенты, номенклатура. Толстый JS-клиент с AJAX-доступом к БД (Access / MSSQL), расширениями и экосистемой АРМ. Live-сессия well показывает отраслевой контур полиграфии / широкоформата / сувенирки (бренд-поток Zaprintom: этикетка, визитки, баннеры, фотокниги, ДТФ, УПД/ЭДО).

fabula.net.ru / localhost:9000 v.12-01 · © 2013–2025 БД well · User Миланин А.А. (live) milanin@mail.ru

1. Назначение и позиционирование

jFabula — браузерный клиент «Оперативный учёт». Исторически это перенос десктопного приложения на MS Access на web-платформу. Среда исполнения — обычный браузер; доступ — интернет/интранет.

Это не «тонкий CRUD-фронт»: справочники и метаданные кэшируются в db.tbl.*, фильтры/расчёты/печать выполняются на клиенте; расширение — через iframe-плагины и спецформы add/sf.
Фрагмент: вкладки и фильтр
Фрагмент оболочки: вкладки модулей и полоса глобального фильтра (live well).

2. Архитектура и стек

СлойКомпонентыРоль
Shell jFabula/forms/main.html, main.js Вкладки, глобальный фильтр, статус-бар, login iframe, PWA manifest
Домен Fabula.js (jf), Fabula.mm.js, Fabula.ext.js, Fabula-tables.js, fabula.min.js (fa) Документы, движения, свойства, плагины, формулы
UI lib/wi.*, lib/mi5.* uiTable, wiProperties, комбо, календарь, диалоги, форум, ФС
Данные lib/db.js (db_Client) Query / apiTbl / getReferences, Profile, isAdmin, Access↔MSSQL, db + dbsys
Сервер AwwS / host HTTP API /db/{dbName}/…, auth /auth/…, опционально WebSocket

Кодировка UI: Windows-1251. Язык интерфейса: русский. PWA: jFabula/manifest.json (display: standalone). Полноценный offline (service worker) в просмотренном коде не обнаружен.

Фрагмент: вкладки и плагины
Фрагмент: строка вкладок + иконки плагинов.

3. Запуск, Auth, bootstrap

Точки входа

Auth (jAuth)

  1. Cookie: Login, dbName, Sha1 (SHA1 от login+password; Guest — фиксированный hash).
  2. POST /auth/{dbName}/login.html с Base64-телом { Sql:'Auth', Login, Sha1, … }.
  3. Успех → db_Client, Rights, Users; вызов main.Start (или pm/sb/am…).
  4. Login=="Agent" → в UI показывается Login2.
  5. ?reload=Y — ускоренный вход по cookie Sha1.

main.Start

  1. Ожидание coreLib, mainTbls, docs.
  2. Guards: User=="0"/; isAdmin("N") без полного admin → /pm.
  3. mainTbls(db); apiTbl (GandsIco, formula); getReferences (Sys, Gands, Firms…).
  4. Profile → Tabs + wi.mainFilterGotoTab(mainTab).
  5. Цепочка ядра: Fabula.js → Fabula.mm.js / fabula.min.js / Fabula.ext.js.

4. Модель данных

Метамодель: Fabula-tables.js (mainTbls), Fabula.mm.js, ReStru.js.

СущностьСмыслСвязи
Docs Хоз. документ / заказ: тип, статус, филиал, агент, фирмы, суммы, долги, НДС, даты 1—N Movement; N—M Property; платежи через PartPay
Movement / Moves Строки: GS, кол-во/цена, CodeOp, фазы MMFlag, MMPID, исполнитель, даты работ N—1 Gands; связь с PM по MMID
Firms / ClientFIO Юрлица и физлица, контакты, холдинг Parent_ID Props; movements
Gands (+ Sys) Номенклатура / системные коды SY*; иерархия кодов GandsExt → formula, plugins, KKT, отчёты
Property EAV: ExtClass (DOCS/FIRMS/Gands…), ExtID, pid pid=0 шапка; pid=MMID строка
Money / Bank / Cash / Salary + PartPay Платежи и разнесение на документы PayID ↔ PPPayID; PPDocID ↔ DocID
Profile / Talk UI-профиль пользователя; обсуждения задач Profile в GandsExt; Talk — лента PM

5. Модуль «Заказы» (docs)

Файлы: forms/docs.html|js, docs.tabs.js, docs.print.js, docs.rep.js.

Фрагмент: список заказов
Фрагмент «Заказы»: список DocID / фирма / сумма / долг (выделен Fi6pa00008).
Фрагмент: строки продукции
Фрагмент: подвкладка «Продукция» — строки Movement выбранного заказа.
Фрагмент: глобальный фильтр
Фрагмент фильтра: даты, филиал, КОП, фирма; справа «Запросы-Отчеты».

Статусы документа

КодСмыслЭффект
DfЧерновикУдаление без F только на Df; выход → MMFlag=1 для GSFlag «У»
RsРезервСимвол в statusSymb
WkПроведёнnon-admin: isEdit=false
Ax / OKАрхив / locknon-admin lock; merge/import skip
BlПринудительный editisEdit=true; ставит только admin F

Доп. гейты: ReadOnly config; чужая заявка; ДатаЗапрета; formula disDocAVR / disDocCompany / disDocType.

Жизненный цикл

Шапка

DocID, Company, DocType, Agent/Manager, FirmContract/FirmCustomer/Person, RegDate / DateAVR / DateAcc / TxtAcc, ParentDoc, Sum1/Sum2, Debt/Debt2, НДС/спецналог, Discount/Margin. Currency в UI закомментирован, поля в SQL остаются.

Строки Movement

Подвкладки документа

TabСодержание
Продукцияdocs.move
Операцииdocs.move2 + move2Set
ОплатыPartPay; AutoPay/ForcePay; ККТ; переход в money
Затратысводка банк/касса + zp/%
МакетыwiImgList из picture-props
SpecFormHTML из DocTypes.SpecForm (в разметке TH может отсутствовать)

Фильтры / Mode0 / HideCosts

DocsFilter: тип, долг, подчинённые, даты, товар/спец, gf.*, заказчик/платёж, propFilter. Mode «оф.» показывает Sum2; jf.Mode0 принудительно включает Mode для non-F; HideCosts прячет колонки и вкладки Операции/Затраты.

6. Модуль «Задачи» (pm)

Файлы: forms/pm.js, pmm.html. Может работать standalone на /pm.

Фрагмент: лента задач
Фрагмент «Задачи»: верх ленты фаз / исполнителей / дат.

7. Модуль «Деньги» и ККТ

Фрагмент: список платежей
Фрагмент «Деньги»: список платежей (тип / суммы / остаток).

PayType → таблицы

PayTypeНазначениеТаблица
деКассаCash
экЭл.кассаCash
рсБанкBank
эдЭл.деньгиBank
чкЧекиBank
баБартерCash
zpПроцентыCash
зпЗарплата (нужен FZ)Salary

ID платежа: {Company}{Y}{PayType}{#####}. В архиве — MoneyAll / PartPayAll / …

Операции

ККТ / atol (add/exts/ext.kkt.js)

8. Контрагенты и номенклатура

Фрагмент: контрагенты
Фрагмент «Контрагенты»: список фирм.
Фрагмент: дерево номенклатуры
Фрагмент «Номенклатура»: дерево групп слева.

Firms

Типы FirmTypes; список + форма Firms/ClientFIO; props; контакты; связанные движения; поиск по ИНН/ОГРН; адрес/карта; холдинг Parent_ID; действие «Обновить ЭДО: Астрал».

Gands (кратко)

Иерархический справочник кодов GSID (2/4/6/8 символов) плюс отдельное дерево ~SYSTEM (SY…) — системные справочники и настройки приложения. Подробности — в § Номенклатура и ~SYSTEM.

Номенклатура и ~SYSTEM — подробное описание

Файлы UI: forms/gands.html|js. Метамодель: Fabula-tables.js (db.tbl.Sys / Gands / SysExts / formula). Live-цифры БД well: Sys ≈ 1+4+34+471 узлов (L2/L4/L6/L8); formula ≈ 469; производные кэши DocTypes 30, CodesOp 371, Agents 406, Storage 16, Regions 89…

1. Как устроена вкладка

Две логические «вселенные» в одной вкладке: товарная номенклатура (Left(GSID,2) <> 'SY'db.tbl.Gands) и системная (Left(GSID,2)='SY'db.tbl.Sys, корень SY = ~SYSTEM).
Фрагмент: корень ~SYSTEM
Фрагмент: в дереве выделен ~System — системный конфиг.
Фрагмент: расширения formula
Фрагмент карточки: GandsExt type=formula (Preview, QR, …) — тот же механизм, что db.tbl.formula.

2. Код GSID и уровни

ДлинаСмыслUI
2Корень раздела (для system — SY)уровень 1
4Раздел / крупная группауровень 2
6Подраздел / типуровень 3
8Лист: конкретный вид / запись справочникауровень 4

Поля записи: GSKindName/GSName, GSCodeNumber (артикул/таб.№), GSCOP, GSUnit, GSFlag, FirmDefault, цены, Sort/Sort4. Расширения — таблица GandsExt (GSExType/Name/Attr1/Attr2/Flag), свойства — Property (ExtClass=Gands).

3. Дерево ~SYSTEM (live well)

~SYSTEM (SY)
├── ВКЛАДКИ (SYВк)       — меню/действия модулей UI и плагины
├── СПРАВОЧНИКИ (SYСП)   — классификаторы, конфигурация, параметры, филиалы
├── ТИПЫ ОПЕРАЦИЙ (SYОП) — DocTypes (продажи/закупки/производство/склад/прочее)
└── СОТРУДНИКИ (SYСо)    — оргструктура → Agents/Users/Profile

3.1. SYВк — ВКЛАДКИ

Конфигурация пунктов меню вкладок приложения (не товар). L6 → модуль; L8 → конкретное действие/отчёт/фильтр/плагин.

Код L6МодульПримеры L8 (well)
SYВкАПАндроид приложениеАРМ водителя (Ав), АРМ кладовщика (Ск)
SYВкПлДеньгиДействия/Импорт, Назначение платежа, Отчеты, Хитрый фильтр
SYВкДпДополнительноДокументы, ФИС; здесь же узел плагинов + GSExType=plugin
SYВкЗаЗадачиДействия, Отчеты, Хитрый фильтр
SYВкОпЗаказыДействия (импорт/меню DocsNew), Отчеты, Хитрый фильтр
SYВкКоКонтрагентыДействия, Отчеты, Хитрый фильтр
SYВкНоНоменклатураДействия, Отчеты, Хитрый фильтр

Типы расширений на вкладках: import (меню импорта), query/query2 (отчёты), plugin (URL в Attr1 через formula), property, fis, help

3.2. SYСП — СПРАВОЧНИКИ (ядро настроек)

L6НазваниеL8 / содержимоеКэш в db.tbl
SYСПКлКлассификаторы ЕИ, Регионы России, Страны, ЭДО gandsUnit (53), Regions (89), providerEDO (52), state/countries
SYСПBPКонфигурация Команды, Константы, Меню строки, Подстановки, Фазы autoSql, template, меню/подстановки строк; фазы связаны с pmState
SYСПКТПараметры главная «панель настроек» системы (см. ниже) CodesOp, Status, Storage, Tags, Pathes, Domain, gandsFlag, KKT/atol, pmState…
SYСПФиФилиалы Листья SYСПФиXX (XX=код филиала: Fi, Ве, АО, Фо…) Companes (14); реквизиты/подписи/НДС/р/с → ourBank, Taxes

SYСПКТ — Параметры (L8, well):

КодНазваниеЧто питает
SYСПКТАИАвтоисправленияПравила AutoCorrect / ReStru
SYСПКТДМДоменыdb.tbl.Domain + динамические Domain(имя) — списки для props (Адрес, КД, КОП, Пункт выдачи…)
SYСПКТRB / АтККТ RBSoft / АтолKKT, atol-команды (GSExType KKT/atol)
SYСПКТCHКонтекстная помощьhelp-тексты
SYСПКТКПКОПCodesOp (~371): иерархия кодов операций — подробно §6
SYСПКТМПМакро-путиPathes: [makets], [docs], [bank], [gands]… → сетевые каталоги
SYСПКТКфОбщиеОбщие константы/режимы (Mode0, DateArx, MainCompany… через formula/config)
SYСПКТСКСкладыStorage (О1 Основной, Р1 Рулонка, Н1 Наружка…)
SYСПКТСтСтатусStatus: Df/Wk/Ax/Bl/Rs/No/nP
SYСПКТТгТегиTags: [1c], [isp], [email], [kop]… разметка UI/печати
SYСПКТФаФазы задачpmState (~28): 1 Черновик… 8/7п/6т…
SYСПКТФНФлаги номенклатурыgandsFlag (D/S/U/А0…)
SYСПКТФЗФоновые заданияtask / фоновые сценарии
SYСПКТШаШаблонtemplate — шаблоны сообщений/текстов

Филиал SYСПФиXX несёт в GandsExt/Property: ИНН/КПП/ОГРН/адреса/телефоны/email, подписи 1-я/2-я, налоги (НДС с датами → Taxes), расчётные счета (р/с → ourBank + привязка KKT), настройки ЭДО. Разбор по well — §7.

3.3. SYОП — ТИПЫ ОПЕРАЦИЙ (DocTypes)

Каждый L6 — семейство документов; L8 — конкретный DocType (ключ = последние 2 символа кода). При создании заказа меню берётся отсюда (DocsNew / SYОП*).

L6СемействоПримеры DocType (well)
SYОПОтПРОДАЖАПо Полиграфия, НИ Наружка.Изготовление, Ус Услуги, До Доставка, Га Газеты, НА Out of Home
SYОППоПРИОБРЕТЕНИЕГазеты, Услуги (закупка)
SYОПВППРОИЗВОДСТВОДизайн, Изготовление, Сборка, Сдельщина, Транспорт, Некондиция, Самореклама…
SYОПСкСКЛАДПриход/Расход накладная, Инвентаризация, Амортизация
SYОППрПРОЧЕЕCRM, Авансовый отчёт, Зарплата, Проекты
SYОПЧОЧастные объявленияотдельный контур ЧО

На типе документа в Exts задаются: фильтры номенклатуры (Фильтр/Фильтр2), подчинённые документы, SpecForm, печатные формы, правила поведения строк.

3.4. SYСо — СОТРУДНИКИ

Оргструктура → Agents / Users. L6 = отдел; L8 = сотрудник (GSCodeNumber = ID пользователя).

L6Отдел (well)
SYСо10Администрация
SYСо20Бухгалтерия
SYСо30Дизайн
SYСо40Продажи
SYСо50Закупки
SYСо61…69Производство: Рулонное / Широкоформат / Наружка / Полиграфия / Постобработка / Сувенирка
SYСо70Водители
SYСо80Zaprintom (внешний канал/агенты)
SYСоСл / Ув / 00 / 99Служебные / Уволенные / Числятся / Чужие

У сотрудника в property: подмена/просмотр (расширение списка Users), склад, контакты, фото. Profile пользователя хранится как GandsExt на его SYСо*-узле (GSCodeNumber=User): Main/Filters/PM/Касса/Эквайринг… (SHA1/Rights в SysExts специально скрываются из общей выборки).

4. Как System «разворачивается» в кэши клиента

При загрузке mainTbls:

  1. Gands WHERE Left(GSID,2)<>'SY' — товары.
  2. Sys WHERE Left(GSID,2)='SY' — system-дерево; из листьев собираются DocTypes, Companes, Agents, Users…
  3. SysExts / sys-import — все GandsExt с GSExID LIKE 'SY%' (кроме formula/config в отдельном потоке).
  4. funTbls раскладывает Exts в специализированные таблицы: plugins, KKT, Storage, Status, Tags, CodesOp, pmState, Pathes, Domain, Regions, Assigning, providerEDO, gandsUnit, ourBank, Taxes, autoSql, template, localReport…
  5. formula (+ formula2 из sys) — ~469 текстовых правил/SQL-фрагментов/шаблонов UI.
Менять ~SYSTEM в UI — это менять поведение всего приложения (меню, типы документов, КОП, фазы, кассы, филиалы). Часть критичных вещей дублируется/маскируется (Rights/SHA1 не светятся в общем SysExts).

5. Товарная номенклатура (не SY)

6. Подробно: SYСПКТКП — КОП (коды операций)

Узел System SYСПКТКП («Параметры. КОП»). Записи GandsExt с этим GSExID (кроме property/help) загружаются в db.tbl.CodesOp. Live well: 371 кода (L1: 9 · L2: 56 · L3: 208 · L4: 98).

Семантика и флаги

Классы L1 (well)

КодКлассФлаг
0Вспомогательные операции
1РЕКЛАМНАЯ ПРОДУКЦИЯ (A)dA
2УПАКОВКА И ЭТИКЕТКА (A)A
3РАЗМЕЩЕНИЕ (A)dA
5ПРОЧЕЕ (A)dA
6ЗАРПЛАТА И НАЛОГИ
7НАКЛАДНЫЕ РАСХОДЫ
8ТМЦ (A)A
9ПРОЧИЕ ОПЕРАЦИИ

Группы L2 — обзор по классам

ДиапазонСмысл (примеры well)
00–03Документооборот (D), работы реклама/этикетка, услуги
10–19Продажи/производство рекламы: дизайн, ШФ, текстиль, наружка, карты, сувенирка, полиграфия, плоттер, УФ
21Этикетка
30–38, 51Размещение: ЧО, OOH, эфир, пресса, доставка, интернет, медийка, аэропорт
61–66Проценты, сдельщина, трудовые, налоги, страхование, зарплата (Z)
70–79Накладные: производство, ОХР, транспорт, а/м, PR, подотчёт, сторонние услуги
80–89ТМЦ/ОС: НМА, компьютеры, оргтехника, транспорт, здания, станки, сырьё, запчасти, МБП
90–99Резерв, вложения, деньги в пути, инвентаризация, займы, отсроченные налоги, внереализационные, капитал

Примеры детализации

00 Документооборот → 001 УПД покупатели, 002 поставщики, 003/004 кассовые ордера, 005 счёт поставщика, 006 материалы, 007 топливо, 00F web Fabula, 00S Zaprintom…

10 Дизайн (A) → 100 почасовой, 101 разработка, 109 предпечатная подготовка.

01 Работа реклама (A) (флаг TA) → 010 макетирование, 0100 креатив, 0101 макетирование, 0120 ШФ, 0140 монтаж наружки, 0142 лазер… — «трудовые» КОП производственных строк.

12 Широкоформат (A) → 120 собственная / 121 сторонняя / 122 ДТФ.

Добавление КОП: новый лист/Ext под SYСПКТКП с GSExType=код операции и именем; после перезагрузки справочников код появится в комбо CodeOp. Менять флаги A/I осторожно — влияют на АВР, проценты и отчёты.

7. Подробно: SYСПФи — филиалы (наши юрлица)

Листья SYСПФиXX (XX = 2-символьный код филиала) → db.tbl.Companes. Расширения филиала (property / «Подпись» / «Налог» / «р/с» / ЭДО / KKT) собираются в Companes + ourBank / Taxes / hash KKT.

Карточка филиала — что хранится

Группа ExtПоляКуда попадает
propertyИНН, КПП, ОГРН/ОКПО, Адрес, Адрес юр., Телефоны, E-mail, Дата АВР, Color, _GUIDCompanes.INN/KPP/…
Подпись / 1-я, 2-ядолжность + ФИОFst*/Snd* для печати счетов/АВР
Налог / НДС, Прибыльставка, период d1–d2ndsTax(d), profitTax, Taxes
р/сномер счёта, БИК, банк, KKT в Attr2, Flag A=defaultourBank / ourBankBr / ourBankHide; RS/BIC на Companes
KKT (часто на SYСПФи* или Параметры)имя кассы, cfg JSON (server, users…)db.tbl.KKT.hash

Филиалы well (Companes)

КодНазваниеИННDefault р/сБанкprofitTaxр/с всего
FiФИЛИАЛ (тест)9102002828290000Тест Филиал7
АООчень Хорошо910200485040702810452720003074Сбербанк410
ФоИП Фомичева Л.В.910200294870…2622Сбербанк528
ЕлИП Елсуков А.Ю.910200282829…2624Сбербанк531
РРРучная работа9102049146…4778Сбербанк48
РПРПП9102048784…97565ВТБ46
ДМДом Рекламы9109004874…2047Сбербанк9
ВеВерант9102162180…1913ВТБ62
РОРА ОХ2301094285…16573Сбербанк Кр.11
ПОВзаимное обеспечение9102219849…0464Сбербанк3
Ко/ЛН/Си/РА*ликвидированные7/…/7/20мало

У многих юрлиц заполнены GUID 1С (Code1C), цвет филиала в UI, email (zaprintom.ru / vwell.su / vwell.biz).

Расчётные счета и ККТ

Как это стыкуется с документами

Docs.Company = код филиала (Fi/АО/Фо/…)
  → Companes[Company] даёт реквизиты печати, НДС, default RS
  → ourBank фильтруется по Gr=Company
  → KKT из профиля Касса/Эквайринг для этого Company
  → Mode0 / MainCompany (formula) влияют на «официальный» филиал
Менять р/с и KKT на филиале — зона кассовой дисциплины. Ликвидированные юрлица помечены «*» в названии, но записи и счета часто остаются для истории документов.

8. Практический смысл для сопровождения

9. Права, Profile, Config, formula

Буквы Rights (db.isAdmin(tag))

Проверка: sIn(Rights, tag.split("")) или полный admin 'A'. В коде часто комбо: CFZ, FBZ, BFL, CWF…

БукваКонтекст
AСуперправа
BБухгалтерия / 1С / ЭДО / фильтры Agent
CКасса / KKT / AutoPay / чеки
DАРМ водителей; ATS
EMoney: ограничения User; del рс/эд
FПолный админ UI
LЗапись Profile (BFL); combo Agent
NТолько /pm
RCombine; docs Bl
SСборная печать
VAdminTools / AutoCorrect
WСклад arm-stock
ZФинансы / зп / проценты
P / T / UATS / forum / редко — слабо задокументированы в JS

Profile / Config

Механизм db.tbl.formula

Runtime-конфигурация и мини-язык выражений: бизнес-правила живут в БД (GandsExt), клиент подставляет/вычисляет их через глобальную formula() (Fabula.mm.js). Live well: ~469 строк → ~425 уникальных ключей в hash.

Фрагмент: Ext type formula
Фрагмент UI: расширения с типом formula (имя + атрибут с {…} / P[1]).

Хранение и загрузка

GandsExt WHERE GSExType = 'formula'
  → db.tbl.formula  (Src: main)
  Sql: SELECT GEIDC, GSExName AS Key,
              GSExAttr1 + iif(Flag LIKE '%d%' AND Attr2 NOT NULL, Attr2, '') AS Val,
              GSExFlag
  funAfterLoad: hash[Key] = r; при дублях имени Val += Val

db.tbl.formula2 — копия схемы, Src: sys (системная БД; в well hash пуст)
db.tbl.atol     — тот же паттерн для GSExType='atol' (команды ККТ)

API formula(parm, isEval, n, args)

ВызовПоведение
formula("MainCompany") Lookup hash.MainCompany.Val; если нет {…} — вернуть текст as-is (напр. [filial]Fi[/filial])
formula("docSale(DocID)") Lookup docSale, подставить аргументы в P[1], P[2]… → результат-строка (часто фрагмент SQL)
formula(text, true) «Раскрыть» вложенные {expr}: lookup имени / sEval JS-выражения; рекурсия до отсутствия { или глубины >100
formula("a,b,c", true) Если все ключи есть в hash — sEval(formula(каждого)) подряд (пакет)
formula("{iif(…)}") / вложенные Вычислить содержимое скобок (доступны $0…$9, fa, db, mi5…)

Мини-язык внутри Val

// пример: предикат «продажа»
docSale.Val ≈ Mid( {"P[1]" || "DocID"}, 4, 2) IN ('ру','рг','по',…)
formula("docSale(DocID)", true)
  → Mid( DocID, 4, 2) IN ('ру','рг',…)

// пример: константа филиала
MainCompany → [filial]Fi[/filial]
DateArx     → 01.01.25

// пример: конфиг ЭДО
Astral.Doki → таблица Fi|Ко|Ел|Фо… → globalId | org id

Классы формул (по применению)

КлассПримеры ключейРоль
Константы / режимыMode0, MainCompany, DateArx, ExtURL, noPropsфилиал по умолчанию, архив, URL
SQL-предикатыdocSale, docBuy, sql*WHERE в отчётах и фильтрах
Проверки / гейтыchkEDO*, chkPay, disDoc*, bad*, need*блокировки UI, валидация
ККТkktTemplate, kktNDS, kktClient, kktOper…сборка JSON чека
ЭДО / оплатыAstral.Doki, PayCompany, Payroll*ящики, выбор филиала оплаты
Хуки жизненного циклаafterDoc, afterMove, change-mov-mmflag, Фазы-*действия после записи / смены фазы (~48 «Фазы*»)
Шаблоны печати/UI*Оферта.*, Счет.*, Меню*, Анкета*тексты/меню через Format
АвтоисправленияcorrectSumDoc, moneyMerge + autoSqlпакетные SQL-фиксы

Well: ~278 с {, ~138 «простых» строк, Flag пуст ~101 / d ~256 / h/hd/dh — скрытие/режимы в UI редактора.

Связь с остальным клиентом

formula(..., true) и блоки {…} выполняют sEval в контексте страницы — это и сила (полный доступ к fa/db), и риск. Опечатка в formula ломает отчёты/чеки/ЭДО без деплоя JS. Дубли имён склеивают Val — следить за уникальностью GSExName.

10. Ядро fa / db / фильтр / WebSocket

fa — текущий контекст

Нет единого store: объект берётся из активной вкладки + кэш fa.doc / fa.move.

APIПоведение
fa.DocТекущий документ (docs/pm/arm/acc)
fa.MoveСтрока Movement; Props.X → Property
fa.Curmoney или Doc
fa.Moneymoney.tbl.Cur()
fa.PropsEAV по pid=0 / MMID

db.Query

formReq → Ajax /db/{dbName}/{CacheName}; Src sys → dbsys; *Src — параллельные запросы. apiTbl — GET готовых таблиц; getReferences — пакетный Preload. Архив: DateArx + gf.Arx → *ARX / *All.

MainFilter

switch(вкладки) → docs/pm/gands/firms/money.Filter. Общие gf.*: Date1/2, Arx, CodeOp, Company, Firm, Agent, WorkerType. Persist Filters в Profile. fa.getFilter — SQL-фрагменты.

WebSocket

db.ws/ws/{db}/{user}. Команды: ping, setflag/settalk → pm.signalPM; msg/reload/tel/signdoc/update. Live в основном для задач/Talk; полный refresh Docs/Money — частичный.

11. Плагины, интеграции, спецформы

В Fabula слово «плагин» означает три разных механизма:

  1. Кнопки вкладки «Плагины» (#main.Plugins) — полноценные iframe-приложения в зоне #supp. Конфиг: SYВкДп + GSExType=plugin. См. § ниже.
  2. setPlugin(url, firm, doc, mmid) — модальный диалог-iframe поверх заказа (счёт, оплата, печать, calc из строки…). Контекст в hash Base64: mmid;doc;docid;firm. Внешние http(s)/kontur открываются в window.open.
  3. add/exts/*.js — встроенные расширения ядра (1С, ЭДО, ККТ, маркировка), не кнопки вкладки.

Кнопки вкладки «Плагины» (toolbar)

Фрагмент: только иконки плагинов
Фрагмент: иконки #main.Plugins (без всей строки вкладок).
Фрагмент: вкладки ФИС
Фрагмент плагина ФИС: Баланс / Прибыль / Капитал / … / Ошибки.

Где в UI

Откуда берётся реестр

GandsExt на SYВкДп, GSExType = "plugin"
  → Fabula-tables.js funTbls:
      db.tbl.plugins.rec.push({
        Key: GSExID,           // "SYВкДп"
        Val: GSExName,         // подпись (title картинки)
        ImportName: formula(GSExAttr1),  // URL
        Ico: GSExAttr2,        // путь или {icon8("…")}
        Flag: GSExFlag         // права / скрытие
      })
  → SubTabs() строит кнопки из plugins.rec

Фильтры показа кнопки

УсловиеЭффект
имя пустое или начинается с * (sEq0(Val,"*"))не попадает в toolbar (скрытый/архивный плагин)
Flag заданкнопка только если db.isAdmin(Flag) (буквы Rights)
Flag пуствидна всем

Live well, User=140, Rights=A: на панели 9 плагинов (+ «Закрыть все»). В SysExts всего 18 записей type=plugin; 9 скрыты префиксом * и/или флагом h.

Каталог well — видимые кнопки

ПодписьURL (ImportName)FlagНазначение
Спецформа (встр.) /add/sf/calc.html?[db] Калькулятор/анкеты продукции; основной встроенный calc в iframe-зоне supp
Файл-сервер /add/sf/fs.html Файловый менеджер (макеты/документы по путям Pathes)
Задачи для водителей /add/am АРМ водителя (доставка/полевые задачи)
Кабинет агента /acc Агентский кабинет (accept / витрина агента)
Сборная печать /add/sf/sborka.html?[db] SF Раскладка/сборка печати; право S или F (сборка)
Атол ККТ /add/sf/atol.html CFW Консоль команд ККТ Атол; права касса/админ/склад
Интернет-магазин https://zaprintom.ru?fabagentid={db.User} → после formula ≈ …=140 Внешняя витрина Zaprintom, привязка к агенту
Автопроверка макетов http://192.168.3.152:4000/ Локальный сервис проверки макетов (интранет)
ФИС /add/sf/fis.html Финансовая аналитика: баланс / прибыль / капитал / ОСВ деньги·покупатели…

Скрытые в реестре (* / Flag h) — well

ИмяURLЗаметка
*Препресс/view? + Base64 путь к sborka170старый просмотр препресса
*Управление задачами/jFabula/specforms/pm.htmlлегаси PM-форма
*Таблица заказов…/page-proofs.htmlлегаси вёрстка
*Wiki-Well/add/sf/wiki.html?WWwiki
*АТС/add/sf/ats.htmlFlag h PVF — телефония
*Наружная реклама…/narujka.htmlотдельный контур OOH
*Сайт «Тильда»http://bord.com.ruвнешний сайт
*Сайт «Очень хорошо»http://www.vwell.bizвнешний сайт
*Тех. поддержка/add/sf/forum.html?[db]форум/help

Как добавить / изменить кнопку

  1. В номенклатуре → ~SYSTEM → ВКЛАДКИ → Дополнительно (SYВкДп).
  2. Ext type plugin: Name = подпись; Attr1 = URL (можно [db], [user], formula {db.User}); Attr2 = иконка (/path.png или {icon8("name")}); Flag = буквы Rights или пусто; имя с * — скрыть с панели, оставить в данных.
  3. Перезагрузка справочников / сессии → кнопка в main.Plugins.
URL с ?[db] после подстановки становится ?well (имя БД). Внешние http(s) в toolbar открываются внутри iframe supp (не через window.open — в отличие от setPlugin("https://…") из заказа).

Отличие от setPlugin из заказа

Кнопка toolbarsetPlugin(…)
Контейнер#supp на всю рабочую областьмодальный .dialog поверх
Контекст doc/mmidнет (форма сама берёт db/cookie)hash Base64 с doc/firm/mmid
Источник URLdb.tbl.plugins / SYВкДпкод модуля, SpecForm, SysExts import, печать
ПримерыФИС, Атол-консоль, fs, Zaprintombill, pay, docs.print, calc из строки

Интеграции ядра (add/exts)

Подключаются из Fabula.ext.js (_require): edo, 1C, marka, kkt. ЭП (ext.eds.js) подгружается лениво из ЭДО при локальной подписи. Внешние HTTP чаще идут через серверный прокси /curl/… + Base64 curl-команды (секреты в {Config.*} / Profile, не в клиентском git).

Карта «кто кого зовёт»

Fabula.ext.js
  ├─ ext.edo.js   (_Astral)  ← firms «Обновить ЭДО», bill/УПД, tasks
  │     └─ ext.eds.js (EDS)  ← КриптоПро CAdES при signDocLocal
  ├─ ext.1C.js    (_1C)      ← иконка [1c] в документах/номенклатуре, ExportDoc
  ├─ ext.marka.js (Marka)    ← ЧЗ/СУЗ, коды в Props, чек с КМ
  └─ ext.kkt.js   (atol)     ← Аванс/Отгрузка/возврат; Preview чека; atol.html

1С — ext.1C.js (_1C)

ЭДО Астрал — ext.edo.js (_Astral)

ЭП КриптоПро — ext.eds.js (EDS)

ККТ — ext.kkt.js (atol)

Маркировка / Честный знак — ext.marka.js (Marka)

Онлайн-оплаты и банк

Платёжная форма /payadd/sf/pay.js

Открывается через setPlugin("/pay?doc=…") (docs, accept, am, tasks). Провайдеры:

КлючТипEndpoint (prod)Подпись
Robokassamoneyauth.robokassa.ru/…SHA1 /getsha1, Config Robokassa-{fil}-Pwd
Unitellercardwpay.uniteller.ruMD5, return → /hookpay
VTB / PayKeepervtb{login}.server.paykeeper.ruBasic Config
Best2Payb2ppay.best2pay.net/webapiMD5
Rnkbrnkbmpi.rncb.ruorder JSON + hookpay
QRMsbpapp.wapiserv.qrm.oooСБП

hookpay.js — callback после оплаты: определяет провайдера по query, проверяет подпись, проводит платёж/PartPay. Return URL-ориентир: https://bord.com.ru.

Импорт банка / эквайринг

Спецформы add/sf (подробнее)

ФормаРольОткрытиеЗаметки
calcКалькулятор/анкета продукцииtoolbar + setPlugin из docscalc-fun.min.js
bill / bill2Счёт, оферта, УПД-контурsetPlugin / печатьтянет ext.edo.js; bill2 — упрощённый Start
pay / hookpayОнлайн-оплата + callbacksetPlugin /payсм. § оплаты
accept → /accКабинет агентаtoolbar /accоплата, счёт, delivery
am → /add/amАРМ водителяtoolbarполевые задачи, оплата
arm-stockАРМ склада/add/stockправо W
sborkaСборная печатьtoolbar (SF)читает parent main.Plugins
fisФин. аналитикаtoolbarБаланс / Прибыль / Капитал / ОСВ…
atol.htmlКонсоль ККТtoolbar (CFW)обёртка atol.Do
fs.htmlФайл-серверtoolbarпути Pathes
tasksФоновые заданияслужебно / SYСПКТФЗККТ close, hook-оплаты, ЭП
forum / wiki / atsподдержка, wiki, АТСскрытые plugin *в SYВкДп, не на панели
i-sprint / vizitka.* / ox.isprintвитрины / статусыспец. URLконтур Zaprintom / интернет-заказов

Конфиг интеграций (где крутить)

МестоЧто хранит
formulaAstral.Doki, kkt*, chkEDO*, PayCompany, шаблоны чеков/проверок
Config / ConfigLoc1c-url, 1c-key, пароли Robokassa/Uniteller/VTB по филиалу
Profileтокен Астрал; Касса / Эквайринг по Company
Companes ExtsCode1C, OMS, р/с+Attr2→KKT, подписи
SysExts SYВкДпкнопки плагинов
providerEDO / Assigning / KKTоператоры ЭДО, шаблоны назначения платежа, кассы
Секреты шлюзов и токены ЭДО/1С — в Config/Profile сервера, не в git. Прокси /curl — единая точка выхода; отладка почти всегда с лога curl в console.

12. Печать, отчёты и хитрые фильтры

Фрагмент: меню отчётов
Фрагмент меню LocalReports: группы Астрал / Деньги / ЗП / Макеты… (query из SYВк*От).

Печать текущего документа

Отчёты — узлы SYВк..От

Кодировка узлов

УзелВкладкаImportName вкладкиLive well
SYВкОпОтЗаказы (docs)docs35 записей (query + печать/договора/реестры)
SYВкЗаОтЗадачи (pm)pm14 query (ЗП, брак, макеты, склад…)
SYВкПлОтДеньги (money)money28 query (поток, займы, ЗП, остатки…)
SYВкКоОтКонтрагентыfirms4 query
SYВкНоОтНоменклатураgands17 query (склад, 1С, formula Stat…)

Два UI-канала

КаналКнопка / вызовЧто берёт из SYВк*От
Печать документа docs.Reports → docs.print Только SYВкОпОт, типы не query, имя без *: Документы / Договора / Реестры / Служебные / ЧО
SQL-/аналитические отчёты gf.LocalReportslocalReport() (lib/wi.js) Все GSExType=query с текущей вкладки (fa.getGands(Left(GSExID,6), ImportName) == main.Tabs.idx); имя без ведущего * (если не admin)
Универсальный report UI forms/reports.js (listGS) Все Exts узла (включая query), дерево по GSExType=группа

Поля Ext отчёта

Язык query-отчётов

{opt(1,"!Дата2") + opt("filter","Dates,CodeOp,Company,Firm,Agent")
 ,opt(2,"Незавершёнка"), …}
SELECT … FROM Moves/Docs …
{fa.getFilter("Dates","GSDt")} {fa.getFilter("Company")}
…

opt/formula собирают UI-переключатели и WHERE из глобального фильтра вкладки. Результат гоняется через wiSql / wiReport.preRender (кнопка LocalReports).

Каталог well — печать (SYВкОпОт, не-query)

ГруппаПримеры
ДокументыСчет, Акт выполненных работ, Заявка на приобретение, Лист заказа (*Счет на оплату — скрыт)
ДоговораПоставка товара, Размещение наружной рекламы → [file][makets]/…
Реестры / Служебныев основном * (скрыты) + Flag F
Частные объявленияЧО. Реестр, ЧО. Экспорт

Каталог well — query по вкладкам (видимые без *)

УзелПримеры отчётов
ОпОтОбороты: Активность / Средний чек / Работы; Топливо; Списанные материалы; Марки на балансу; Стимулирование; Деление базы 2025…
ЗаОтЗП дизайнерам / сдельно / ОТК / транспорт; Брак; Макеты динамика/отменённые; Склад ГП; загрузка исполнителей
ПлОтДеньги. Поток / Подотчет / Транзит / Инкассация / Депозиты; Займы.*; ЗП.*; RoboKassa; Остатки по счетам; движение по КОП
КоОтМёртвые клиенты; Ответственные; Рекламные компании
НоОтСклад: Остатки / Инвентаризация / Фотоформы / Выгрузка; Листопроходы; Синхронизация с 1С; formula Stat; Марки…
Тип query2 → таблица db.tbl.localReport (отдельный канал); в общем SysExts узлы SY%ХФ не грузятся (GSExID NOT LIKE 'SY%ХФ') — только через SmartFilter.

Хитрые фильтры — узлы SYВк..ХФ

Назначение

Не «отчёт на экран», а готовый SQL-предикат для списка текущей вкладки: выбирается в комбо «Ещё…» / title «Хитрый фильтр» справа у prop-фильтра и добавляется в WHERE (propFilter.getFilterSF() → AND к Filter вкладки).

Привязка код ↔ System

МодульSmartFilterGSТаблица кэшаКонтейнер UI
docsSYВкОпХФsmFilterDocdpFilter.SM
pmSYВкЗаХФsmFilterPMppFilter.SM
moneySYВкПлХФsmFilterMoneympFilter.SM
firmsSYВкКоХФsmFilterFirmfpFilter.SM
gandsSYВкНоХФsmFilterGandsgpFilter.SM

Реализация: wiPropFilter в lib/wi.combo.js. Загрузка: SELECT … FROM GandsExt WHERE GSExID=… AND Left(Name,1)<>'*' AND Type<>'formula'. Дерево: GSExType = группа (часто «[red]Ошибки[/red] …»), листья = пункты фильтра.

Как собирается WHERE

  1. Пользователь выбирает один/несколько пунктов в Tree-комбо SM (value через ;).
  2. getFilterSF для каждого пункта берёт FiltWhere = Attr1 (или Attr, если Flag содержит d).
  3. Плейсхолдер {input} → prompt; **%; затем formula(sf).
  4. Модуль: wh += AND (sf) вместе с обычным prop-фильтром (Свойство=Значение) и глобальным main.filter.

Счётчики [2]/[] в имени — live-статистика (funStat / CountSql модуля): сколько записей попадёт под фильтр.

Каталог well — хитрые фильтры

УзелNГруппы / пункты
ОпХФ14 Ошибки в оплате: можно слить оплаты, неправильный долг, ФИО ЧЛ, нет связи с платежом;
в строках: не задан Товар/КОП/Дата, плохое подчинение;
в шапке: затраты (подряд/проценты/деньги), N заявки, повтор свойств, пустые строки, сумма≠строки;
+ formula correctSumDoc (не в комбо Type≠formula)
ЗаХФ1Ошибки: Повторение свойств
ПлХФ8 Задвоение номера; слить банк/кассу/проценты; неправильный остаток; несовпадение контрагента/ФИО/филиала; плохой номер; + formula moneyMerge
КоХФ3 Задвоение ИНН / Названия; «Не было движения»
НоХФ1Был отрицательный остаток
Хитрые фильтры — мощный инструмент контроля качества данных («красные ошибки»). Менять Attr1 = менять SQL по всей вкладке; проверять на Fi/копии. Type formula на ХФ — служебные правила (correctSumDoc, moneyMerge), не пункты комбо.

Как добавить отчёт или хитрый фильтр

  1. Печатная форма заказа: Ext на SYВкОпОт, Type=«Документы» (или Договора…), Attr1=путь HTML/[file], без * в имени.
  2. Аналитика вкладки: Ext на соответствующий SYВк*От, Type=query, Attr1=SQL/{opt…}; Flag=буквы прав; * в имени — черновик/скрытый.
  3. Хитрый фильтр: Ext на SYВк*ХФ, Type=группа («Ошибки…»), Name=подпись [n], Attr1=SQL-условие по ключу списка (DocID / MMID / PayID / FirmID / GSID); без Type=formula.

13. Live UI (сессия БД well)

Проверено в браузере агента: http://localhost:9000/jFabula/db/well?reload=Y (User=Миланин А.А., v.12-01). Загружается ~34 script-модуля (common/core/wi/Fabula/forms…). Скриншоты сохранены в Fabula.doc.img/.

Заказы
Заказы — список
Задачи
Задачи — лента
Отчёты
Меню отчётов
ФИС
ФИС — вкладки

Заказы

Задачи (PM)

Деньги

Контрагенты

Номенклатура

Плагины (кнопки title → URL)

Краткий снимок live; полный разбор UI/конфига/скрытых — §11 кнопки «Плагины».

НазваниеURL / путьFlag
Спецформа (встр.)/add/sf/calc.html?[db]
Файл-сервер/add/sf/fs.html
Задачи для водителей/add/am
Кабинет агента/acc
Сборная печать/add/sf/sborka.html?[db]SF
Атол ККТ/add/sf/atol.htmlCFW
Интернет-магазинhttps://zaprintom.ru?fabagentid={db.User}
Автопроверка макетовhttp://192.168.3.152:4000/
ФИС/add/sf/fis.html

14. Экосистема и развёртывание

ПриложениеURL / путьНазначение
Фабула/jFabulaОсновной клиент
PM/pmУправление проектами (standalone)
АРМ водителя/add/amМобильные/полевые задачи
Кабинет агента/accАгентский кабинет
АРМ склада/add/stockКладовщик
Сборная печать/sbПроизводство / раскладка
Спецформа calc/add/sf/calc.htmlКалькулятор
Интернет-магазин:8000Витрина
Wiki-Well/add/sf/wiki.htmlБаза знаний
Файл-менеджер/add/sf/fs.htmlФайлы
MobulaMobula.apkAndroid WebView-оболочка АРМ

Мобильная версия: наличие и особенности

Короткий вердикт: отдельной «мобильной Фабулы» как переписанного responsive-клиента нет. Основной jFabula — толстый десктопный UI с узкими адаптациями под телефон/планшет. Реальная мобильная работа строится на отдельных АРМ (+ Android APK Mobula), а не на полном наборе вкладок docs/pm/money.

1. Что есть в основном клиенте (jFabula)

jFabula на узком экране (~400px), вкладки сокращены, Status3 скрыт
Основной shell на ~400px (эмуляция Android): вкладки без текста, плотные гриды остаются «десктопными». Полный кадр: fabula-12-mobile-shell-full.png.

2. Чего нет

3. Настоящий мобильный контур = АРМ + APK

КаналГдеОсобенности
АРМ водителя /add/am, add/sf/am.html + am.js Упрощённый UI задач/гео; в Start принудительно window.AA = 1. Флаг isMobula: !!window.AndroidFunction — мост в нативную оболочку.
АРМ склада плагин → arm-stock.html / /add/stock Складские операции на планшете/терминале, не полный jFabula.
Кабинет агента /acc Отдельное лёгкое приложение агента.
Mobula.apk раздача с index.html/downloads/Mobula.apk Android-клиент под полевые АРМ (WebView + AndroidFunction). Рядом опционально Browser APK; GeoFabula/fabula.apk в раздаче закомментированы.
Плагины из основной Фабулы кнопки «Задачи для водителей», склад и т.п. (SYВкДп) С десктопа можно открыть мобильный АРМ в iframe/вкладке supp; на телефоне — fullscreen при AA.

4. Практическая модель использования

Офис / широкий экран  →  полный jFabula (docs, pm, money, firms, gands, SYSTEM)
Узкий браузер         →  тот же jFabula + ужатие shell (w800); полный учёт «на коленке»
Поле / склад / агент  →  /add/am, arm-stock, /acc  ±  Mobula.apk (AndroidFunction)

Итог для внедрения: мобильность — это линейка узких АРМ и оболочка Mobula, а не паритет функций с десктопной Фабулой. PWA-манифест — задел «иконка на домашний экран», не offline-ERP.

15. Сквозные сценарии

Заказ → оплата → чек

DocsNew (SYОП*) → NewItem/calc строки → статус Wk
  → docs.pay AutoPay/ForcePay → PartPay
  → atol.KKT (Аванс/Отгрузка) → Property _KKT
  → печать Счёта/АВР

Строка → задача PM

Movement + MMFlag → docs.move.toPM / goLink(pm, MMID)
  → фазы, Talk, сигналы → goLink(docs, doc&mmid)

Импорт банка → разнесение

MenuImport → importMoney.fun_* → Bank/Cash
  → money.pay.payDoc → PartPay → CorrectMoney

Плагин из документа

SpecForm / Bill / calc / внешний URL
  → setPlugin(form, firm, doc, mmid) → iframe Start()

16. Ключевые файлы и символы

СимволФайлРоль
jf / jFabulaFabula.jsДоменный фасад, плагины, Mode0, goLink
fafabula.min.jsКонтекст Doc/Move/Cur/Props
db_Clientlib/db.jsQuery, справочники, Profile, isAdmin, ws
wi / uiTablelib/wi.*UI-контролы и гриды
formulaGandsExtRuntime-конфиг из БД
main.Startforms/main.jsBootstrap вкладок и фильтра
setPluginFabula.jsЗапуск спецформ/плагинов
docs / pm / money / firms / gandsforms/*Основные модули UI
atolext.kkt.jsККТ

17. Ограничения разбора

  • Полный справочник Status и семантика OK/Bl кроме lock/unlock выведены из ветвлений кода.
  • Полный список банков импорта и URL плагинов живут в данных БД (GandsExt), не в JS.
  • Буквы U/P/T вне узких мест слабо задокументированы.
  • money.setConfigconfigDocs выглядит как легаси/баг.
  • Ветка fa.Props для gands может ссылаться на необъявленный props.
  • Service worker / полноценный offline PWA не подтверждён.

18. Преимущества и недостатки текущего проекта

Оценка по коду + live-сессии well. Это зрелая отраслевая система «под производство», а не зелёный greenfield-продукт.

Преимущества

  • Полный операционный контур в одном клиенте: заказ → строки/калькулятор → фазы производства (PM) → оплаты/ККТ → печать/ЭДО.
  • Глубокая предметная модель Docs/Movement/Property/PartPay закрывает сложные полиграфические и сервисные сценарии (материалы, работы, подряд, макеты, доставка).
  • Расширяемость без переписывания ядра: плагины iframe, спецформы, formula/GandsExt, SysExts — бизнес-правила часто в данных, не только в коде.
  • Гибрид SaaS + локальная БД (AwwS) — ответ на требования по связи и хранению данных у заказчика.
  • Экосистема АРМ: водитель, склад, агент, сборка, магазин, Mobula, автопроверка макетов, ФИС.
  • Интеграции «в бою»: 1С, Астрал ЭДО, КриптоПро, Атол ККТ, маркировка, онлайн-оплаты, импорт банков.
  • Права-теги и Profile позволяют тонко резать UI/операции по ролям без отдельных приложений.
  • Долгая эксплуатация (2013–2025) и живая нагрузка: тысячи задач, крупные суммы, многофилиальные кассы.
  • Толстый клиент: после прогрева справочников работа с фильтрами/таблицами отзывчива; часть логики не ждёт round-trip на каждое действие.

Недостатки

  • Устаревший фронтенд-стек: vanilla JS, Windows-1251, декларативный HTML+eval-паттерны, нет современного фреймворка/типизации — высокий порог входа для новых разработчиков.
  • Монолитные файлы (docs.js / Fabula.js / money.js на тысячи строк) усложняют тестирование, ревью и безопасный рефакторинг.
  • UI «десктоп 2000-х» в браузере: плотные таблицы, сокращённые подписи вкладок, слабая мобильная адаптация основного shell (отдельные АРМ компенсируют частично).
  • Скрытая конфигурация в БД (formula, plugins URL, права-буквы) — поведение системы трудно воспроизвести «из git»; документация прав неполная.
  • Техдолг и легаси-ловушки: закомментированный UI, подозрительные ветки (money→configDocs), мёртвый/хрупкий код, eval/sEval, Base64-контексты плагинов.
  • Безопасность/современные практики: Sha1 пароля, cookie-auth модели эпохи, смешение SQL на клиенте — требует осторожности при публикации в открытый интернет.
  • Наблюдаемость и качество: нет явного слоя автотестов/CI в клиенте; отладка через console/«Отладка Zaprintom»; регрессии ловятся вручную.
  • Масштабирование команды: знания «в голове автора» и в формулах БД; онбординг дорогой.
  • PWA/offline заявлены слабо: manifest есть, полноценный offline не подтверждён; зависимость от доступности сервера/прокси.
  • Плотность live-UI (пагинация по 4000, огромные гриды) — риск деградации на слабых машинах/сетях без жёсткого paging/virtualization.

Итоговая оценка

Сильная сторона — соответствие реальному производственному процессу (полиграфия/реклама) и богатство интеграций. Слабая сторона — стоимость сопровождения и эволюции из‑за толстого legacy-клиента и конфигурации «в данных». Рациональная стратегия: не «переписать всё», а окантовывать ядро (спецформы/плагины/API), постепенно выносить горячие модули, фиксировать formula/права в репозитории и наращивать регрессионные сценарии по заказу→PM→оплате.