Перейти до основного вмісту

Створювані за допомогою скриптів робочі процеси з Beancount і Fava

Beancount (інструмент обліку у форматі звичайного тексту з подвійним записом) і Fava (його веб-інтерфейс) є дуже розширюваними та створюваними за допомогою скриптів. Їхній дизайн дозволяє автоматизувати фінансові завдання, генерувати власні звіти та налаштовувати сповіщення за допомогою скриптів Python. За словами одного користувача: "Мені дуже подобається, що мої дані в такому зручному форматі, і мені подобається, що я можу автоматизувати все, що завгодно. Немає API, як файл на вашому диску; його легко інтегрувати." Цей посібник проведе вас через створення робочих процесів, які можна створювати за допомогою скриптів — від простої автоматизації для початківців до розширених плагінів Fava.

Початок роботи: Запуск Beancount як скрипту Python

scriptable-workflows

Перш ніж занурюватися в конкретні завдання, переконайтеся, що Beancount встановлено (наприклад, через pip install beancount). Оскільки Beancount написаний на Python, ви можете використовувати його як бібліотеку у власних скриптах. Загальний підхід такий:

  • Завантажте свою бухгалтерську книгу Beancount: використовуйте завантажувач Beancount, щоб проаналізувати файл .beancount в об’єкти Python. Наприклад:

    from beancount import loader
    entries, errors, options_map = loader.load_file("myledger.beancount")
    if errors:
    print("Errors:", errors)

    Це дає вам список entries (транзакції, залишки тощо) і options_map з метаданими. Усі ваші рахунки, транзакції та залишки тепер доступні в коді.

  • Використовуйте мову запитів Beancount (BQL): замість ручної ітерації ви можете запускати SQL-подібні запити до даних. Наприклад, щоб отримати загальні витрати за місяць, ви можете скористатися API запитів:

    from beancount.query import query
    q = query.Query(entries, options_map)
    result = q.query("SELECT month, sum(position) WHERE account ~ 'Expenses' GROUP BY month")
    print(result)

    Це використовує систему запитів Beancount для агрегування даних. (По суті, це схоже на те, що робить команда bean-query, але тут ви використовуєте її у скрипті.) Фактично, автор Beancount зазначає, що ви можете завантажити файл і викликати run_query() безпосередньо через API Python, уникаючи необхідності викликати зовнішні команди в циклі.

  • Налаштуйте структуру проєкту: упорядкуйте свої скрипти разом із бухгалтерською книгою. Зазвичай розташовують каталоги для імпортерів (для отримання/аналізу зовнішніх даних), звітів або запитів (для скриптів аналізу) і документів (для зберігання завантажених виписок). Наприклад, один користувач зберігає:

    • importers/ – власні скрипти імпорту Python (з тестами),
    • queries/ – скрипти для створення звітів (запускаються за допомогою python3 queries/...),
    • documents/ – завантажені банківські CSV/PDF-файли, упорядковані за рахунком.

За допомогою цієї установки ви можете запускати скрипти вручну (наприклад, python3 queries/cash_flow.py) або запланувати їх (за допомогою cron або засобу запуску завдань) для автоматизації робочого процесу.

Автоматизація завдань звірки

Звірка означає перевірку відповідності вашої бухгалтерської книги зовнішнім записам (банківським випискам, звітам за кредитними картками тощо). Бухгалтерська книга у форматі звичайного тексту Beancount і API Python дозволяють автоматизувати значну частину цього процесу.

Імпорт і зіставлення транзакцій (для початківців)

Для початківців рекомендованим підходом є використання плагінів імпорту Beancount. Ви пишете невеликий клас Python, дотримуючись протоколу імпорту Beancount, щоб проаналізувати заданий формат (CSV, OFX, PDF тощо) і створити транзакції. Потім використовуйте команду bean-extract або скрипт, щоб застосувати ці імпортери:

  • Напишіть імпортер (клас Python з такими методами, як identify(), extract()) для формату CSV вашого банку. Документація Beancount містить посібник і приклади.
  • Використовуйте bean-extract у скрипті або Makefile (як у прикладі justfile) для аналізу нових виписок. Наприклад, один робочий процес запускає bean-extract для всіх файлів у ~/Downloads і виводить транзакції у тимчасовий файл.
  • Вручну перегляньте та скопіюйте транзакції з тимчасового файлу у свою основну бухгалтерську книгу, потім запустіть bean-check, щоб переконатися, що залишки збігаються.

Хоча цей процес все ще включає етап перевірки, значна частина трудомісткої роботи з аналізу та форматування записів автоматизована. Скрипти імпорту можуть також автоматично призначати категорії та навіть встановлювати твердження щодо залишку (твердження очікуваних залишків) для виявлення розбіжностей. Наприклад, після імпорту ви можете мати рядок на кшталт 2025-04-30 balance Assets:Bank:Checking 1234.56 USD, який підтверджує кінцевий залишок. Коли ви запускаєте bean-check, Beancount перевірить, чи всі ці твердження щодо залишку правильні, і позначить будь-які помилки, якщо транзакції відсутні або дублюються. Це найкраща практика: автоматично генеруйте твердження щодо залишку для кожного звітного періоду, щоб комп’ютер міг виявляти не узгоджені відмінності за вас.

Спеціальні скрипти звірки (середній рівень)

Для більшого контролю ви можете написати власний скрипт Python для порівняння списку транзакцій банку (CSV або через API) із записами вашої бухгалтерської книги:

  1. Прочитайте зовнішні дані: проаналізуйте CSV-файл банку за допомогою модуля csv Python (або Pandas). Нормалізуйте дані в список транзакцій, наприклад, кожна з датою, сумою та описом.
  2. Завантажте транзакції бухгалтерської книги: використовуйте loader.load_file, як показано раніше, щоб отримати всі записи бухгалтерської книги. Відфільтруйте цей список до потрібного рахунку (наприклад, ваш поточний рахунок) і, можливо, діапазону дат виписки.
  3. Порівняйте та знайдіть невідповідності:
  • Для кожної зовнішньої транзакції перевірте, чи існує ідентичний запис у бухгалтерській книзі (зіставте за датою та сумою, можливо, описом). Якщо не знайдено, позначте його як "новий" і, можливо, виведіть як транзакцію у форматі Beancount для перегляду.
  • І навпаки, визначте будь-які записи бухгалтерської книги на цьому рахунку, які не відображаються у зовнішньому джерелі – це можуть бути помилки введення даних або транзакції, які не були проведені банком.
  1. Виведіть результати: надрукуйте звіт або створіть новий фрагмент .beancount з відсутніми транзакціями.

Як приклад, скрипт спільноти під назвою reconcile.py робить саме це: враховуючи файл Beancount і вхідний CSV-файл, він друкує список нових транзакцій, які слід імпортувати, а також будь-які наявні записи бухгалтерської книги, яких немає у вхідних даних (потенційно ознака неправильної класифікації). За допомогою такого скрипту щомісячна звірка може бути такою ж простою, як його запуск, а потім додавання запропонованих транзакцій до вашої бухгалтерської книги. Один користувач Beancount зазначає, що вони "проводять процес звірки для всіх рахунків щомісяця" і використовують зростаючу колекцію коду Python для усунення значної частини ручної роботи з імпорту та звірки даних.

Порада: Під час звірки використовуйте інструменти Beancount для точності:

  • Використовуйте твердження щодо залишку, як згадано вище, щоб автоматично перевіряти залишки на рахунках.
  • Використовуйте директиву pad, якщо потрібно, яка може автоматично вставляти збалансувальні записи для незначних розбіжностей заокруглення (використовуйте з обережністю).
  • Напишіть модульні тести для своєї логіки імпорту або звірки (Beancount надає допоміжні функції тестування). Наприклад, один робочий процес включав взяття зразка CSV-файлу, написання невдалих тестів з очікуваними транзакціями, а потім реалізацію імпортера, доки всі тести не будуть успішно пройдені. Це гарантує, що ваш скрипт імпорту працює правильно для різних випадків.

Створення спеціальних звітів і підсумків

Хоча Fava надає багато стандартних звітів (Звіт про прибутки та збитки, Баланс тощо), ви можете створювати спеціальні звіти за допомогою скриптів. Вони можуть варіюватися від простих вихідних даних консолі до файлів із форматуванням або діаграм.

Запит даних для звітів (для початківців)

На базовому рівні ви можете використовувати мову запитів Beancount (BQL), щоб отримувати зведені дані та друкувати або зберігати їх. Наприклад:

  • Підсумок руху грошових коштів: Використовуйте запит для обчислення чистого руху грошових коштів. "Рух грошових коштів" можна визначити як зміну залишку певних рахунків за певний період. Використовуючи BQL, ви можете зробити так:

    SELECT year, month, sum(amount)
    WHERE account LIKE 'Income:%' OR account LIKE 'Expenses:%'
    GROUP BY year, month

    Це об’єднає всі записи доходів і витрат за місяць. Ви можете запустити це через CLI bean-query або через API Python (query.Query, як показано раніше), а потім відформатувати результат.

  • Звіт про витрати за категоріями: Запитайте загальні витрати за категоріями:

    SELECT account, round(sum(position), 2)
    WHERE account ~ 'Expenses'
    GROUP BY account
    ORDER BY sum(position) ASC

    Це дає таблицю витрат за категоріями. Ви можете запустити кілька запитів у скрипті та вивести результати у вигляді тексту, CSV або навіть JSON для подальшої обробки.

Один користувач вважав "тривіальним" аналізувати фінансові дані за допомогою Fava або скриптів, посилаючись на те, що вони використовують один скрипт Python для отримання даних із Beancount за допомогою мови запитів, а потім поміщають їх у DataFrame Pandas для підготовки спеціального звіту. Наприклад, ви можете отримати щомісячні підсумки за допомогою запиту, а потім використати Pandas/Matplotlib для побудови графіка руху грошових коштів з часом. Комбінація BQL і бібліотек науки про дані дозволяє створювати звіти, які виходять за рамки того, що Fava пропонує за замовчуванням.

Розширене звітування (діаграми, ефективність тощо)

Для більш розширених потреб ваші скрипти можуть обчислювати показники, як-от ефективність інвестицій, або створювати візуальні вихідні дані:

  • Ефективність інвестицій (IRR/XIRR): оскільки ваша бухгалтерська книга містить усі грошові потоки (купівлі, продажі, дивіденди), ви можете обчислити ставки прибутковості портфеля. Наприклад, ви можете написати скрипт, який фільтрує транзакції ваших інвестиційних рахунків, а потім обчислює внутрішню норму прибутковості. Існують бібліотеки (або формули) для обчислення IRR на основі даних про грошові потоки. Деякі розроблені спільнотою розширення Fava (як-от PortfolioSummary або fava_investor) роблять саме це, обчислюючи IRR та інші показники для інвестиційних портфелів. Як скрипт, ви можете використовувати функцію IRR (з NumPy або власної), у серії внесків/зняття коштів плюс кінцеве значення.

  • Багатоперіодні або власні показники: потрібен звіт про вашу норму заощаджень (відношення заощаджень до доходу) щомісяця? Скрипт Python може завантажити бухгалтерську книгу, підсумувати всі рахунки доходів і всі рахунки витрат, потім обчислити заощадження = дохід - витрати та відсоток. Це може вивести гарну таблицю або навіть створити звіт HTML/Markdown для ваших записів.

  • Візуалізація: ви можете створювати діаграми за межами Fava. Наприклад, використовуйте matplotlib або altair у скрипті, щоб створити діаграму чистої вартості з часом, використовуючи дані бухгалтерської книги. Оскільки бухгалтерська книга містить усі історичні залишки (або ви можете накопичувати їх, повторюючи записи), ви можете створювати графіки часових рядів. Збережіть ці діаграми як зображення або інтерактивний HTML. (Якщо ви віддаєте перевагу візуальним елементам у програмі, див. розділ розширення Fava нижче, щоб додати діаграми всередині Fava.)

Параметри виведення: Вирішіть, як надати звіт:

  • Для одноразового аналізу може бути достатньо друку на екрані або збереження у файл CSV/Excel.
  • Для інформаційних панелей розгляньте можливість створення HTML-файлу з даними (можливо, за допомогою бібліотеки шаблонів, як-от Jinja2, або навіть просто написання Markdown), який можна відкрити у браузері.
  • Ви також можете інтегруватися з Jupyter Notebooks для інтерактивного середовища звітування, хоча це більше для дослідження, ніж для автоматизації.

Запуск сповіщень із вашої бухгалтерської книги

Іншим потужним використанням робочих процесів, які можна створювати за допомогою скриптів, є налаштування сповіщень на основі умов у ваших фінансових даних. Оскільки ваша бухгалтерська книга регулярно оновлюється (і може містити датовані майбутнім елементи, як-от майбутні рахунки або бюджети), ви можете сканувати її за допомогою скрипту та отримувати сповіщення про важливі події.

Попередження про низький залишок на рахунку

Щоб уникнути овердрафтів або підтримувати мінімальний залишок, вам може знадобитися сповіщення, якщо будь-який рахунок (наприклад, поточний або ощадний) опуститься нижче порогового значення. Ось як це можна реалізувати:

  1. Визначте поточні залишки: після завантаження entries через завантажувач обчисліть останній залишок на потрібних рахунках. Ви можете зробити це, агрегуючи записи або використовуючи запит. Наприклад, використовуйте запит BQL для залишку на певному рахунку:

    SELECT sum(position) WHERE account = 'Assets:Bank:Checking'

    Це повертає поточний залишок на цьому рахунку (суму всіх його записів). Крім того, використовуйте внутрішні функції Beancount для створення балансу. Наприклад:

    from beancount.core import realization
    tree = realization.realize(entries, options_map)
    acct = realization.get_or_create(tree, "Assets:Bank:Checking")
    balance = acct.balance # an Inventory of commodities

    Потім отримайте числове значення (наприклад, balance.get_currency_units('USD') може дати Decimal). Однак використання запиту простіше в більшості випадків.

  2. Перевірте поріг: порівняйте залишок із попередньо визначеним лімітом. Якщо нижче, запустіть сповіщення.

  3. Запустіть сповіщення: це може бути так само просто, як друк попередження в консолі, але для реальних сповіщень ви можете надіслати електронний лист або push-сповіщення. Ви можете інтегруватися з електронною поштою (через smtplib) або службою, як-от IFTTT або API веб-перехоплювача Slack, щоб надіслати сповіщення. Наприклад:

    if balance < 1000:
    send_email("Low balance alert", f"Account XYZ balance is {balance}")

    (Реалізуйте send_email з даними вашого поштового сервера.)

Запускаючи цей скрипт щодня (за допомогою cron job або Windows Task Scheduler), ви отримаєте активні попередження. Оскільки він використовує бухгалтерську книгу, він може враховувати всі транзакції, включно з тими, які ви щойно додали.

Майбутні терміни сплати

Якщо ви використовуєте Beancount для відстеження рахунків або термінів, ви можете позначити майбутні платежі та налаштувати скрипти для нагадування. Два способи представлення майбутніх зобов’язань у Beancount:

  • Події: Beancount підтримує директиву event для довільних датованих нотаток. Наприклад:

    2025-05-10 event "BillDue" "Mortgage payment due"

    Це не впливає на залишки, але записує дату з міткою. Скрипт може сканувати entries для записів Event, де Event.type == "BillDue" (або будь-який власний тип, який ви оберете) і перевіряти, чи дата знаходиться в межах, скажімо, наступних 7 днів від сьогодні. Якщо так, запустіть сповіщення (електронною поштою, сповіщенням або навіть спливаючим вікном).

  • Майбутні транзакції: деякі люди вводять датовані майбутнім транзакції (пост-датовані) для таких речей, як заплановані платежі. Вони не відображатимуться в залишках, доки не настане дата (якщо ви не запускаєте звіти станом на майбутні дати). Скрипт може шукати транзакції, датовані найближчим майбутнім, і перелічувати їх.

Використовуючи це, ви можете створити скрипт "нагадування", який під час запуску виводить список завдань або рахунків, термін виконання яких настає найближчим часом. Інтегруйтеся з API, як-от Google Calendar, або менеджером завдань, якщо ви хочете автоматично створювати нагадування там.

Виявлення аномалій

Окрім відомих порогових значень або дат, ви можете створювати за допомогою скриптів спеціальні сповіщення про незвичайні шаблони. Наприклад, якщо зазвичай щомісячна витрата не відбулася (можливо, ви забули сплатити рахунок), або якщо витрати категорії аномально високі цього місяця, ваш скрипт може позначити це. Зазвичай це передбачає запит останніх даних і порівняння з історією (що може бути розширеною темою – можливо, із застосуванням статистики або машинного навчання).

На практиці багато користувачів покладаються на звірку для виявлення аномалій (неочікуваних транзакцій). Якщо ви отримуєте банківські сповіщення (як-от електронні листи для кожної транзакції), ви можете проаналізувати їх за допомогою скрипту та автоматично додати їх до Beancount або принаймні перевірити, чи вони записані. Один ентузіаст навіть налаштував свій банк на надсилання електронних листів зі сповіщеннями про транзакції з планом аналізувати та додавати їх до бухгалтерської книги автоматично. Таке сповіщення, кероване подіями, може гарантувати, що жодна транзакція не залишиться незаписаною.

Розширення Fava за допомогою власних плагінів і переглядів

Fava вже можна створювати за допомогою скриптів через систему розширень. Якщо ви хочете, щоб ваша автоматизація або звіти інтегрувалися безпосередньо у веб-інтерфейс, ви можете написати розширення Fava (також зване плагіном) на Python.

Як працюють розширення Fava: Розширення — це модуль Python, який визначає клас, що успадковує fava.ext.FavaExtensionBase. Ви реєструєте його у своєму файлі Beancount за допомогою власної опції. Наприклад, якщо у вас є файл myextension.py з класом MyAlerts(FavaExtensionBase), ви можете ввімкнути його, додавши до своєї бухгалтерської книги:

1970-01-01 custom "fava-extension" "myextension"

Під час завантаження Fava імпортує цей модуль та ініціалізує ваш клас MyAlerts.

Розширення можуть робити кілька речей:

  • Перехоплювачі: вони можуть перехоплювати події в життєвому циклі Fava. Наприклад, after_load_file() викликається після завантаження бухгалтерської книги. Ви можете використати це для запуску перевірок або попереднього обчислення даних. Якщо ви хотіли реалізувати перевірку низького залишку всередині Fava, after_load_file міг би повторити залишки на рахунках і, можливо, зберегти попередження (хоча виведення їх в інтерфейс може вимагати трохи більше роботи, наприклад, викликати FavaAPIError або використовувати Javascript для показу сповіщення).
  • Спеціальні звіти/сторінки: якщо ваш клас розширення встановлює атрибут report_title, Fava додасть нову сторінку на бічній панелі для нього. Потім ви надаєте шаблон (HTML/Jinja2) для вмісту цієї сторінки. Ось як ви створюєте абсолютно нові перегляди, як-от інформаційну панель або підсумок, яких Fava не має за замовчуванням. Розширення може збирати будь-які необхідні дані (ви можете отримати доступ до self.ledger, який містить усі записи, залишки тощо), а потім відтворити шаблон.

Наприклад, вбудоване розширення portfolio_list у Fava додає сторінку зі списком ваших позицій портфеля. Розширення спільноти йдуть далі:

  • Інформаційні панелі: плагін fava-dashboards дозволяє визначати власні діаграми та панелі (за допомогою бібліотек, як-от Apache ECharts). Він читає конфігурацію YAML для запуску запитів, виконує їх через Beancount і генерує сторінку динамічної інформаційної панелі у Fava. По суті, він поєднує дані Beancount і бібліотеку діаграм JavaScript для створення інтерактивних візуалізацій.
  • Аналіз портфеля: розширення PortfolioSummary (внесок користувачів) обчислює підсумки інвестицій (групування рахунків, обчислення IRR тощо) і відображає їх в інтерфейсі Fava.
  • Перегляд транзакцій: інше розширення, fava-review, допомагає переглядати транзакції з часом (наприклад, щоб переконатися, що ви не пропустили жодних квитанцій).

Щоб створити просте розширення самостійно, почніть з підкласу FavaExtensionBase. Наприклад, мінімальне розширення, яке додає сторінку, може виглядати так:

from fava.ext import FavaExtensionBase

class HelloReport(FavaExtensionBase):
report_title = "Hello World"

def __init__(self, ledger, config):
super().__init__(ledger, config)
# будь-яка ініціалізація, можливо, проаналізувати конфігурацію, якщо надано

def after_load_file(self):
# (необов’язково) запустити після завантаження бухгалтерської книги
print("Бухгалтерська книга завантажена з", len(self.ledger.entries), "записами")

Якщо ви розмістите це в hello.py і додасте custom "fava-extension" "hello" до своєї бухгалтерської книги, Fava покаже нову сторінку "Hello World" (вам також знадобиться файл шаблону HelloReport.html у підпапці templates, щоб визначити вміст сторінки, якщо розширення використовує лише перехоплювачі). Шаблон може використовувати дані, які ви додаєте до класу розширення. Fava використовує шаблони Jinja2, тому ви можете відтворити свої дані в таблиці HTML або діаграмі в цьому шаблоні.

Примітка: Система розширення Fava є потужною, але вважається "нестабільною" (може змінюватися). Вона вимагає певного знайомства з веб-розробкою (HTML/JS), якщо ви створюєте власні сторінки. Якщо ваша мета — просто запускати скрипти або аналізи, може бути простіше зберігати їх як зовнішні скрипти. Використовуйте розширення Fava, коли вам потрібен спеціальний досвід у програмі для вашого робочого процесу.

Інтеграція API та даних сторонніх розробників

Однією з переваг робочих процесів, які можна створювати за допомогою скриптів, є можливість отримання зовнішніх даних. Ось поширені інтеграції:

  • Обмінні курси та товари: Beancount не отримує ціни автоматично за задумом (щоб звіти залишалися детермінованими), але він надає директиву Price для вказівки курсів. Ви можете автоматизувати отримання цих цін. Наприклад, скрипт може запитувати API (Yahoo Finance, Alpha Vantage тощо) для отримання останнього обмінного курсу або ціни акцій і додавати запис ціни до вашої бухгалтерської книги:

    2025-04-30 price BTC 30000 USD
    2025-04-30 price EUR 1.10 USD

    Існують інструменти, як-от bean-price (тепер зовнішній інструмент під парасолькою Beancount), які отримують щоденні котирування та виводять їх у форматі Beancount. Ви можете запланувати запуск bean-price щоночі для оновлення файлу включення prices.beancount. Або використовуйте Python: наприклад, за допомогою бібліотеки requests для виклику API. Документація Beancount пропонує, щоб для акцій, що публічно торгуються, ви могли "викликати певний код, який завантажить ціни та запише директиви для вас." Іншими словами, дозвольте скрипту здійснити пошук і вставити рядки price, замість того, щоб ви робили це вручну.

  • Дані фондового портфеля: подібно до обмінних курсів, ви можете інтегруватися з API, щоб отримувати детальні дані про акції або дивіденди. Наприклад, Yahoo Finance API (або бібліотеки спільноти, як-от yfinance) може отримувати історичні дані для тікера. Скрипт може оновлювати вашу бухгалтерську книгу щомісячною історією цін для кожної акції, якою ви володієте, забезпечуючи точні історичні звіти про ринкову вартість. Деякі власні розширення (як-от fava_investor) навіть отримують дані про ціни на льоту для відображення, але найпростіше — регулярно імпортувати ціни до бухгалтерської книги.

  • Банківські API (відкритий банкінг/Plaid): замість завантаження CSV-файлів ви можете використовувати API для автоматичного отримання транзакцій. Служби, як-от Plaid, агрегують банківські рахунки та надають програмний доступ до транзакцій. У розширеній установці у вас може бути скрипт Python, який використовує API Plaid для щоденного отримання нових транзакцій і збереження їх у файл (або безпосередньо імпортує до бухгалтерської книги). Один досвідчений користувач створив систему, де Plaid передає дані до їхнього конвеєра імпорту, роблячи їхні книги майже автоматичними. Вони зазначають, що "ніщо не заважає вам зареєструватися в Plaid API та зробити те саме локально" – тобто ви можете написати локальний скрипт для отримання банківських даних, а потім використати свою логіку імпортера Beancount для їх аналізу в записи бухгалтерської книги. Деякі регіони мають відкриті банківські API, надані банками; їх можна використовувати аналогічно.

  • Інші API: ви можете інтегрувати інструменти бюджетування (експортувати заплановані бюджети для порівняння з фактичними в Beancount) або використовувати API OCR для читання квитанцій і автоматичного зіставлення їх із транзакціями. Оскільки ваші скрипти мають повний доступ до екосистеми Python, ви можете інтегрувати все: від служб електронної пошти (для надсилання сповіщень) до Google Sheets (наприклад, оновлювати аркуш щомісячними фінансовими показниками) до програм обміну повідомленнями (надсилати собі підсумковий звіт через Telegram-бот).

Під час використання API сторонніх розробників не забувайте **захищати свої облі