Информация по установке и настройке модуля net_billing
========================================================

Версия модуля: 1.13
Назначение: Синхронизация данных между биллинговой системой и ERP
  (тарифы, услуги, абоненты, адреса, IP и пр.)


Содержимое архива
-----------------

  billing.php                  - Основной скрипт модуля (точка входа)
  billing.conf.php             - Основной файл конфигурации
  conf/                        - Каталог для конфигов отдельных провайдеров
    kazna39db.conf.php-example - Пример конфига для провайдера kazna39db
  providers/                   - Каталог с провайдерами биллингов
    standart.php               - Провайдер через API (uBilling, MikBill и пр.)
    carbon5.php                - Провайдер через API (Carbon Billing 5.x+)
    kazna39.php                - Провайдер АСР КАЗНА-39 через API
    kazna39db.php              - Провайдер АСР КАЗНА-39 через прямое подключение к БД
  classes/                     - Служебные классы модуля


1. Системные требования и зависимости
-------------------------------------

  Минимальная версия PHP: 7.3

  Обязательные расширения PHP:

    curl      - HTTP-запросы к ERP и API биллинга (без него модуль не запустится)
    json      - кодирование/декодирование данных API (встроено в PHP 8.0+)
    mbstring  - корректная работа с UTF-8 (кириллица в адресах, ФИО и пр.)

  Расширения для работы с БД (только для DB-провайдеров, например kazna39db):

    mysqli    - для MySQL / MariaDB (по умолчанию)
    pgsql     - для PostgreSQL (если $billingDbProvider = 'postgresql')
    oci8      - для Oracle (если $billingDbProvider = 'oracle')

    Для API-провайдеров (standart, carbon5, kazna39) расширения БД не требуются.

  Внешние PHP-библиотеки (Composer) не требуются. Модуль полностью автономен.

  Прочие системные требования:

    - Сетевой доступ к ERP, для API-провайдеров, к серверу биллинга
    - Доступ к серверу БД биллинга (только для DB-провайдеров)


2. Установка
------------

2.1. Поместите все файлы модуля в отдельный каталог на сервере, например:

       /opt/net_billing/

2.2. Создайте каталог для логов и дайте права на запись:

       mkdir -p /var/log/net_billing
       chmod 755 /var/log/net_billing


3. Выбор провайдера биллинга
----------------------------

Модуль поддерживает несколько биллинговых систем. Выбор осуществляется
параметром $billingName в файле billing.conf.php.

  +-----------+---------------------------------------------------+------------------+
  | Значение  | Биллинг                                           | Способ работы    |
  +-----------+---------------------------------------------------+------------------+
  | standart  | uBilling, MikBill и другие совместимые биллинги    | Через API       |
  | carbon5   | Carbon Billing 5.15.06+                           | Через API        |
  | kazna39   | АСР КАЗНА-39                                      | Через API        |
  | kazna39db | АСР КАЗНА-39                                      | Через БД напрямую|
  +-----------+---------------------------------------------------+------------------+

Примеры URL для API-провайдеров (указываются в $billingUrl):

  uBilling:       http:///ubilling/?module=remoteapi&key=BILLING_KEY&action=userside
  MikBill:        http:///api/index/api?key=BILLING_KEY
  Carbon Billing: http://:8082/system_api/?model=Abonents&context=userside
  АСР КАЗНА-39:   https:///admin/index.cgi?get_index=us_api&key=keyus&cat=module

Для провайдеров, работающих через API (standart, carbon5, kazna39):
  - Параметр $billingUrl обязателен
  - Подключение к БД биллинга не требуется

Для провайдеров, работающих через БД (kazna39db):
  - Параметр $billingUrl не используется (можно оставить пустым)
  - Требуется указать параметры подключения к БД в конфиге провайдера


4. Настройка основного конфига billing.conf.php
-----------------------------------------------

Откройте файл billing.conf.php и укажите необходимые значения:


  $billingName = "standart";
  ──────────────────────────────────────────────────────────────────────
  Имя провайдера биллинга. Определяет, с какой биллинговой системой
  будет работать модуль и каким способом (через API или напрямую через БД).

  Допустимые значения:
    "standart"  - uBilling, MikBill и другие совместимые биллинги (через API)
    "carbon5"   - Carbon Billing 5.15.06+ (через API)
    "kazna39"   - АСР КАЗНА-39 (через API)
    "kazna39db" - АСР КАЗНА-39 (через прямое подключение к БД)

  Значение должно точно совпадать с именем файла провайдера в каталоге
  providers/ (без .php) и именем PHP-класса внутри него.

  При смене провайдера достаточно изменить только это значение
  и настроить соответствующие параметры (URL или подключение к БД).


  $erpUrl = "http://erp.domain.com";
  ──────────────────────────────────────────────────────────────────────
  Полный URL-адрес вашей ERP-системы.
  Модуль обращается к API для загрузки и обновления данных.


  $erpApiKey = "key";
  ──────────────────────────────────────────────────────────────────────
  API-ключ для доступа к ERP. Используется модулем при каждом
  обращении к ERP для авторизации запросов.


  $billingUrl = "http://billing.domain.com/...";
  ──────────────────────────────────────────────────────────────────────
  URL-адрес API вашей биллинговой системы. Через этот адрес модуль
  получает данные из биллинга (абоненты, тарифы, адреса и пр.).

  Используется ТОЛЬКО для API-провайдеров (standart, carbon5, kazna39).
  Для DB-провайдеров (kazna39db) оставьте пустым: $billingUrl = "";

  Формат URL зависит от типа биллинга:

    uBilling:
      "http:///ubilling/?module=remoteapi&key=&action=userside"

    MikBill:
      "http:///api/index/api?key="

    Carbon Billing:
      "http://:8082/system_api/?model=Abonents&context=userside"

    АСР КАЗНА-39 (API):
      "https:///admin/index.cgi?get_index=us_api&key=&cat=module"

  Замените , , ,  на реальные значения
  вашего сервера биллинга и ключа доступа.


  $billingId = 1;
  ──────────────────────────────────────────────────────────────────────
  Порядковый номер (ID) биллинга, зарегистрированного в ERP.

  Где взять: в ERP перейдите:
    Настройки -> Биллинги
  Найдите нужный биллинг в списке - его номер (ID) указан в первой колонке.

  Если биллинг один - обычно это значение 1.


  $logPath = "/var/log/net_billing";
  ──────────────────────────────────────────────────────────────────────
  Абсолютный путь к каталогу, в котором модуль будет создавать лог-файлы.
  Каталог должен существовать до запуска модуля и быть доступен на запись
  для пользователя, от имени которого запускается PHP (обычно www-data).

  Создание каталога:
    mkdir -p /var/log/net_billing
    chmod 755 /var/log/net_billing

  В этом каталоге будут созданы файлы:
    {moduleName}.log        - основной лог работы модуля
    {moduleName}_debug.log  - отладочный лог (при включённом $isDebugMode)
    {moduleName}_db.log     - лог SQL-запросов к БД биллинга
    {moduleName}.lock       - файл блокировки (предотвращает параллельный запуск)


  $isSilence = 0;
  ──────────────────────────────────────────────────────────────────────
  Управление выводом сообщений в консоль (stdout).

  Допустимые значения:
    0 - обычный режим: информационные сообщения выводятся в консоль.
        Удобно при ручном запуске и отладке - видно ход выполнения.
    1 - тихий режим: сообщения в консоль не выводятся.
        Рекомендуется при работе через cron, чтобы не засорять почту
        и системный лог cron-демона.

  На запись в лог-файлы этот параметр НЕ влияет (логи пишутся в обоих режимах).


  $isWithoutLog = 0;
  ──────────────────────────────────────────────────────────────────────
  Управление записью лог-файлов.

  Допустимые значения:
    0 - логирование включено: все события записываются в лог-файлы.
        Рекомендуется для нормальной работы.
    1 - логирование отключено: лог-файлы не создаются и не пополняются.
        Может быть полезно при тестировании или нехватке дискового пространства.

  На вывод в консоль этот параметр НЕ влияет (консоль регулируется $isSilence).

  --- Флаги управления поведением синхронизации ---

  $confIsDisableCreateAddress = 0;
    При 1 запрещает создание новых адресных объектов (улиц, домов и пр.) в ERP.
    Полезно, если адресная база в ERP ведётся вручную.

  $confIsSkipUpdateAgreementDate = 0;
    При 1 пропускает обновление даты договора абонента.

  $confIsSkipUpdateDateActivity = 0;
    При 1 пропускает обновление даты последней активности абонента.

  $confIsSkipDeleteEmptyIp = 0;
    При 1 не удаляет пустые (отсутствующие в биллинге) IP-адреса из ERP.

  $confSkipDeleteIp = [];
    Массив диапазонов IP, которые не будут удаляться из ERP.
    Пример: $confSkipDeleteIp = ['10.0.0.0/8', '172.16.0.0/12'];

  $confIsForceDeleteEmptyIp = 0;
    При 1 принудительно удаляет IP из ERP, если их нет в биллинге.

  $confIsImportLessAddress = 0;
    При 1 обновляет абонентов в ERP, у которых нет адреса (пустой адрес).

  $confIsImportLessPhone = 0;
    При 1 обновляет абонентов в ERP, у которых нет телефона.

  $confIsUpdateEmptyLevel = 0;
    При 1 обновляет этаж абонента, если он пустой в ERP.

  $confIsUpdateEmptyEntrance = 0;
    При 1 обновляет подъезд абонента, если он пустой в ERP.

  $confIsSkipUnusedAddress = 0;
    При 1 пропускает неиспользуемые адреса (к которым не привязаны абоненты).

  $confAlwaysSetCustomerGroupId = '';
    Принудительно задать ID группы для всех абонентов. Пустая строка - не менять.

  $confIsUseStreetFullName = 0;
    При 1 использовать полное название улицы с префиксом/суффиксом
    (например, "ул. Ленина" вместо "Ленина").

  $confIsImportMessage = 0;
    При 1 импортировать сообщения из биллинга в ERP.

  $confIsSkipSyncCustomerIsCorporate = 0;
    При 1 не синхронизировать признак "юридическое лицо" у абонента.

  $confIsRemoveEmptyGroups = 0;
    При 1 удалять пустые группы в ERP (группы без абонентов).

  $confIsRemoveEmptyMarkMerge = 0;
    При 1 удалять метки, значения которых не совпадают с markMerge.

  $confIsDoNotUpdateAddPhone = 0;
    При 1 не обновлять дополнительные телефоны абонента.

  --- Дополнительные поля абонента ---

  Для импорта произвольных полей из биллинга в доп. поля ERP используйте:

    $additionalCustomerDataMerge[1] = 1; // [billing.field_id] = erp.field_id
    $additionalCustomerDataMerge[2] = 2;

  Где ключ - ID поля в биллинге, значение - ID доп. поля в ERP.


5. Конфиг провайдера (для DB-провайдеров)
-----------------------------------------

При выборе DB-провайдера (kazna39db) дополнительные настройки выносятся
в отдельный файл conf/{billingName}.conf.php. Модуль автоматически проверяет
наличие этого файла и подключает его, переопределяя параметры из billing.conf.php.

Схема загрузки:
  1. Загружается billing.conf.php -> определяется $billingName
  2. Проверяется существование conf/$billingName.conf.php
  3. Если файл найден - загружается и переопределяет совпадающие переменные
  4. Если не найден - используются параметры из billing.conf.php

Для провайдера kazna39db:
  
  Откройте conf/kazna39db.conf.php и укажите:

  --- Подключение к БД биллинга ---

  $billingDBHost     = '192.168.0.1';     Хост сервера БД
  $billingDBUser     = 'root';            Пользователь БД
  $billingDBPassword = 'password';        Пароль БД
  $billingDBName     = 'kazna39';         Имя базы данных
  $billingDBPort     = '';                Порт (пустой = порт по умолчанию)

  Поддерживаемые СУБД: MySQL, PostgreSQL, Oracle.

  В этом же файле можно переопределить общие параметры ($erpUrl, $erpApiKey,
  $billingId, $logPath, $isSilence), а также задать специфичные настройки
  провайдера kazna39db:

  --- Настройки адресов ---

  $confAdrDistrictMode = 0;
    Режим работы с районами:
      0 - стандартный
      1 - добавлять название района к названию улицы
      2 - использовать название района как название города
      3 - использовать город из districts.city

  $confAddressSrc = '';
    Источник адреса: 'builds' (по умолчанию) или 'users_pi'.

  $confIsImportOnlyUsedAddress = 0;
    При 1 импортировать только адреса, к которым привязаны абоненты.

  $confAddressListCityIds = '';
    Список ID городов для импорта (через запятую). Пустая строка - все города.

  --- Настройки абонентов ---

  $confDateConnectSrc = 1;
    Источник даты подключения:
      1 - users.registration
      2 - dv/internet_log.start

  $confUserImportExpr = '';
    Выражение фильтрации при импорте абонентов (SQL WHERE).

  $confUserStateSrc = '';
    Источник статуса абонента: 'dm.disable' (по умолчанию) или 'u.disable'.

  $confUserAccountSrc = 'bill_id';
    Источник лицевого счёта: 'uid' или 'bill_id' (по умолчанию).

  $confWorkState2 = 0;
    Статус "Не активизирован" отображать как:
      0 - Заблокирован, 1 - Приостановлен, 2 - Активен

  $confWorkState5 = 1;
    Статус "Слишком маленький депозит" отображать как:
      0 - Заблокирован, 1 - Приостановлен, 2 - Активен

  --- Дополнительные поля ---

  $confAddFieldPhone     = '';    Имя поля телефона в users_pi (по умолчанию "phone")
  $confAddFieldCellPhone = '';    Имя поля мобильного в users_pi
  $confAddFieldEntrance   = '';    Имя поля подъезда в users_pi
  $confAddFieldFloor      = '';    Имя поля этажа в users_pi

  --- Импорт расширенных данных ---

  $confImportCustomerTaxNumber = 0;   Импорт ИНН в доп. поле ERP
  $confTaxNumberField          = '';   Имя поля ИНН в таблице users

  $confImportCustomerPassport  = 0;   Импорт паспортных данных в доп. поле ERP
  $confPassportField           = '';   Имя поля паспорта в таблице users

  $confImportCustomerNasIp     = 0;   Импорт IP NAS-сервера в доп. поле ERP
  $confImportCustomerNasPort   = 0;   Импорт порта NAS-сервера в доп. поле ERP
  $confImportCustomerNasName   = 0;   Импорт имени NAS-сервера в доп. поле ERP
  $confImportCustomerNasVlan   = 0;   Импорт VLAN NAS-сервера в доп. поле ERP
  $confImportCustomerGroup     = 0;   Импорт группы абонента (groups.name) в доп. поле ERP

  --- Пароли и безопасность ---

  $confIsSavePasswordToComment = 0;
    При 1 сохранять пароль абонента в комментарий в ERP.

  $confPasswordSecretKey = '';
    Секретный ключ для расшифровки пароля (из config.pl - $conf{secretkey}).

  $confIsImportPasswordToUsPassword = 1;
    При 1 импортировать пароль биллинга в поле пароля абонента ERP.

  --- Источники IP и данных ---

  $confIsCidIp = 0;
    При 1 IP-адрес абонента берётся из dv/internet_log.CID.

  $confIsIpAdrOnlyFromDhcpHosts = 0;
    При 1 IP берётся только из таблицы dhcphosts_hosts.

  $confIsIpAdrSkipFromDhcpHosts = 0;
    При 1 пропускать IP из таблицы dhcphosts_hosts.

  $confIsHideDvLogData = 0;
    При 1 не импортировать данные из таблицы dv/internet_log.

  $confIsHideIpAdrFromDvCalls = 0;
    При 1 не импортировать IP из таблицы dv/internet_calls.

  $confIsHideCidFromDvMain = 0;
    При 1 не импортировать CID из таблицы dv/internet_main.

  $confIsImportTags = 0;
    При 1 импортировать теги абонентов.

  $confIsImportMsg = 1;
    При 1 импортировать сообщения из биллинга.

  $confIsPrimaryDvModule = 0;
    При 1 использовать только DV-модуль.

  --- Контакты ---

  $confContactTypeIdPhone     = '';   ID типа контакта "Телефон" в ERP
  $confContactTypeIdCellPhone = '';   ID типа контакта "Мобильный" в ERP


6. Первый запуск
----------------

6.1. Перейдите в каталог модуля и запустите вручную:

       cd /opt/net_billing
       php billing.php

     Модуль должен отработать без ошибок и вывести:

       net_billing v.1.13.318
       ====================================
        Start module at 2026-03-02 12:00:00
       Finish module at 2026-03-02 12:05:00
       ====================================

6.2. Запустите модуль повторно (2-3 раза).

     При первом запуске будут созданы многие объекты в ERP (тарифы, адреса,
     абоненты). Чем больше данных - тем дольше это займёт.

     При втором запуске сверяются все данные; он тоже может длиться долго,
     так как после первого запуска объекты могут содержать неполные данные.

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

6.3. Проверьте визуально полноту импортированных данных в ERP.


7. Добавление в cron
--------------------

Когда убедитесь, что модуль работает стабильно, добавьте его в cron
(укажите нужные пути):

  */10 * * * * cd /opt/net_billing && php billing.php

При работе через cron рекомендуется включить тихий режим в конфиге:

  $isSilence = 1;


8. Дополнительные возможности
-----------------------------

Принудительное снятие блокировки:

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

    php billing.php --force

Режим отладки:

  В billing.php переменная $isDebugMode = 1 включает расширенное логирование
  в файл {moduleName}_debug.log. Полезно при первичной настройке и диагностике.

Логи модуля (создаются в каталоге $logPath):

  {moduleName}.log        - Основной лог работы
  {moduleName}_debug.log  - Отладочный лог (при $isDebugMode = 1)
  {moduleName}_db.log     - Лог SQL-запросов к БД биллинга


9. Краткая справка: переключение между провайдерами
---------------------------------------------------

Чтобы переключить модуль на другой биллинг, достаточно:

  1. В billing.conf.php изменить $billingName на нужное значение:

       $billingName = "standart";    // API-провайдер (uBilling, MikBill)
       $billingName = "carbon5";     // API-провайдер (Carbon Billing)
       $billingName = "kazna39";     // API-провайдер (АСР КАЗНА-39)
       $billingName = "kazna39db";   // DB-провайдер  (АСР КАЗНА-39)

  2. Для API-провайдеров: указать $billingUrl (URL API биллинга)
     Для DB-провайдеров: оставить $billingUrl пустым

  3. Для DB-провайдеров: создать и заполнить conf/{billingName}.conf.php
     с параметрами подключения к БД

  4. Перезапустить модуль: php billing.php