Добавить комментарий

Типовая схема биллинга

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

В итоге сейчас уже имея довольно большой опыт работы с АСР я решил сделать эталонную схему. Но так-как я все же один человек, то для ее улучшения, надо показать другим и подвергнуть критике. Так что я надеюсь их эта тема заинтересует и они мне расскажут где у меня плохо, а где хорошо. В дальнейшем когда схема будет уже как-то внятно сформирована, я выложу ее на github с документацией, ER-диаграммой и готовой схемой для РСУБД (скорее всего это будет PostgreSQL).

Прежде чем переходить к описанию приведу схему в виде ER-диаграммы

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

  • Договор клиента и ведение его баланса
  • Начисление услуг и их стоимость
  • Предоставление скидок
  • Проведение платежей
  • Перевод денежных средств
  • Ввод остатков клиента из другой системы
  • Счета выставленные клиенту и их погашение

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

Внешние ключи идут в формате id_<имя таблицы>. В случае если ссылок несколько или идут на саму таблицу допускается или дополнение к названию вида id_<имя таблицы>_<поясняющее дополнение> или же id_<поясняющее дополнение>. В качестве примера id_trx_from, id_trx_to для первого случая и id_revoke, id_revoked для второго случая в таблице bill.transfer.

Поля с деньгами определены как numeric(10,2). Если есть возражения почему так не стоит делать, я желаю их услышать.

Поля с датой имеют префикс dt в обязательном порядке. Поля с датой и временем имеют префикс ts в обязательном порядке.

В случае если имеется временной интервал (dtfrom, dtto или tsfrom, tsto), то первая дата всегда задана и по умолчанию равна now(), вторая дата может быть пустой и в этом случае интервал считается действующим на данный момент.

В части случаев у справочников вместо числового первичного ключа используется текстовый мнемонический ключ. Такие ключи обозначены как sid. Используется исключительно для удобства при работе с данными напрямую через консоль РСУБД.

Ну а теперь переходим к описанию схемы. Для начала перечислю опорные таблицы:

  • Договор (bill.contract) - описание договора в самом его минимальном с моей точки зрения проявлении.
  • Проведенные операции (bill.trx) - проведенная на договоре операция. Просто сумма денег в плюс или минус на счету.
  • Отчетные периоды (bill.period) - отчетный период в бухгалтерском смысле слова. Хотя и содержит дату начала и дату завершения, на самом деле практически всегда месяц.
  • Документы к оплате (bill.invoce) - выставленный клиенту по договору

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

Для начала пройдемся по таблицам которые уточняют операции:

  • Тип операции (bill.trxtype) - собственно указывает на тип операции. К примеру начисление (charge), платеж (payment), скидка (discount), перевод (transfer), остатки(remain). Да названия совпадают не случайно.
  • Остатки (bill.remain) - входящие остатки. Входящие остатки должны быть всегда. Иначе через год концов, что было при миграции не найдете. Да и в любой нормальной системе положено что клиент входит с нулем. Дополнительно это позволяет корректировать этот самый входящий остаток если к примеру в предыдущей системе он был не верный. Остаткам в типах операции trx соотвествует 'remain'
  • Платежи (bill.payment) - поступающие платежи. Дополнительно есть таблица с типами платежей (bill.paymenttype) для разделение безнал, нал и т.п.
  • Переводы (bill.transfer) - перевод денежных средств со счета на счет. Замечу, что переводы больше баланса делать не стоит.
  • Начисления (bill.charge) - начисления за потребленные или предоставляемые (при авансе) услуги.
  • Скидки (bill.discount) - скидки на услуги. Тут остановлюсь по подробнее. Хотя в целом в бух учете нет единого мнения как выражать скидку, я выражаю ее в качестве денежного эквивалента к определенному начислению. Это упрощает ее учет.

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

Теперь давайте обратим внимание следующий момент у всех уточняющих таблиц.

Наличие id_revoke и id_revokedby - эти ключи указывают на саму таблицу и применяются при отмене операции. Замечу, что отмены операции для проведенных операций нет. Это сделано, чтобы не возникало проблем вида, мы отменили операцию платежа, операцией начисления. При проведении отмены операции, в соответствующую таблицу добавляется запись с суммой с обратным знаком и проставляются id_revoke у записи отмены и id_revokedby у записи которую отменили. Оба ключа заполнены понятное дело не могут. Стоит избегать операций удаления и изменения. Т.е. если у нас в базу добавлена неверная запись, то ее надо отменить, а потом добавить правильную запись.

Остальные общие поля у этих таблиц я думаю понятны и пояснений не требуют. Если не понятно пишите в комментарии.

Переходим к остальным таблицам:

  • Услуги (bill.service) - услуги предоставляемые клиенту.
  • Единицы измерения (bill.unit) - Единицы измерения. К примеру можно взять из ОКЕИ.
  • Цены (bill.price) - Стоимость услуги. Так-как может изменяться в течении времени, то имеется временной интервал.
  • История балансов (bill.balance) - история балансов с привязкой к проводимым операциям. Чисто справочная таблица для построения отчетов и общего удобства.

И дополнительно пройдемся по таблицам связывающим документ к оплате с проведенными операциями:

Услуги выставляемые в документе для оплаты (bill.invoice_trx) - услуги выставляемые в счете

Платежи покрывающие документ для оплаты (bill.invoice_cover_trx) - платежи покрывающие счет, amount указывает на остаток, после покрытия счета. Если платеж полностью ушел в оплату счета, то тут 0. Если частично, то остаток. Необходим исключительно из-за того что платеж может покрывать два документа по оплате.

Ну и пожалуй на этом пока все.

Теперь про то что в данный момент не учтено в схеме:

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

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