=======
Биллинг
=======


К кому идти: @itjune, @art, @dmitriyt
Со стороны Биллинга: @halty, @quark, @buxxter


С Биллинговым API (XMLRPC) мы работаем через клиент ``yandex_directory.common.billing.client.BillingClient``.
Директория обеспечивает сбор и отправку в Биллинг данных по потребленным услугам для всех смежных сервисов.


Платный режим
=============

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

Как выглядит переход на платный режим пошагово, после нажатия пользователем кнопки "перейти на платный режим":

    1. Создать клиента для организации в Биллинге
    2. Создать плательщика в Биллинге
    3. Создать оферту или договор в биллинге для нашего плательщика
    4. Записать в нашу базу данные о клиенте и плательщике (``OrganizationBillingInfoModel``)

После чего включается платный режим самой организации (Коннекта): ``subscription_plan: paid`` или какие-нибудь платные сервисы.


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

(это еще не запущено)
Если пользователь - юр. лицо и хочет договор, то механизм включения платного режима немного отличается.
Оферта принимается сразу, а договор пользователю необходимо подписать. Поэтому мы должны сформировать договор в виде PDF, пользователь его скачает,
подпишет и оправит нам обратно.
После проверки нашим бэкофисом, договор подписывается со стороны Яндекса. Для нас это выглядит так: с самого начала
после создания договора он находится в неактивном статусе. Мы периодически по крону проверяем его (``check_inactive_contracts.py``)
и в случае если договор стал активным - включаем платный режим в организации.


Подсчет потребленных продуктов
==============================

Вкратце, для того чтобы Биллинг начал списывать деньги с наших клиентов (организаций), мы должны сложить в специальные дневные таблицы в YT данные в виде:

+------------+------------+-----------+
| client_id  | product_id | quantity  |
+============+============+===========+
|...         | ...        | ...       |
+------------+------------+-----------+

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

С лицензиями все немного сложнее. :) Мы каждую ночь складываем в специальную таблицу ``organizations_license_consumed_info``
список всех текущих лицензий по сервисам. При каждом их изменении в таблицу дописываются данные (но не удаляются). Таким образом
в ней у нас хранится полный список пользователей, имевших доступ к этому сервису за любой день.
На следующую ночь из этой таблицы данные перекладываются в ``organizations_billing_consumed_info``.
При этом продукт для каждого сервиса высчитывается динамически, например с учетом примененного промокода.
Список цен представляет собой словарь, ключи которого - количество пользователей, значения - id продуктов::

    {
        1: 100,
        2: 200,
        3: 300
    }

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

После подсчета потребленных продуктов нам нужно сложить их в YT. Складываем мы в два кластера (hahn и banach), на всякий случай, если вдруг один будет лежать.
Отправляем мы всё транзакционно, т.е. либо все данные из базы легли в один из кластеров, либо ничего не создалось.
Биллинг читает только из одного кластера (hahn), переключается вручную при необходимости.


Оплата
======

Чтобы пользователь мог оплатить, его нужно сначала сделать представителем клиента.

Процесс оплаты (``get_url_for_paying``), допустим пользователь хочет положить на счет N рублей:

    1. Проверяем что организация действительно платная
    2. Делаем пользователя представителем клиента
    3. Создаем в биллинге заказ на N продуктов стоимостью в 1 руб.
    4. Получаем ссылку на оплату этого заказа

Пользователь уходит в Биллинг по ссылке и пополняет лицевой счет.


Тестинг
=======

В тестинге Биллинг использует продакшеновые uid-ы, а мы - тестовые. Поэтому у нас есть специальный клиент ``BillingClientWithUidReplacement``,
который умеет подменять uid-ы из под которых мы ходим в биллинг.
Плюс надо помнить, что периодически Биллинг переливает продакшен базу в тестинг, поэтому в тестинге данные могут теряться. Наш QA ходит в продакшен Биллинга.
