Я как человек измученный нарзаном различными АСР и сам принимавший участие в разработке АСР регулярно сталкивался с отсутствием какой-то эталонной схемы биллинга, которую можно было бы посмотреть для оценки АСР, а так же перед созданием своего биллинга. В сети есть некоторое количество работ по этой теме к примеру я в свое время при написании диплома курил вот этот вот труд
Методы моделирования и разработки биллинговых систем. Диплом же и есть диплом и тащить из него схемы странное занятие, так-как реалиям оно отвечает от слова никак.
В итоге сейчас уже имея довольно большой опыт работы с АСР я сделал эталонную схему. Но так-как я все же один человек, то для ее улучшения, надо вытащить на свет божий и подвергнуть критике. Среди читателей же журнала, народа который так же измучен нарзаном различными АСР не мало, так что я надеюсь их эта тема заинтересует и они мне расскажут где у меня плохо, а где хорошо. В дальнейшем когда схема будет уже как-то внятно сформирована, я выложу ее на github с документацией, ER-диаграммой и готовой схемой для РСУБД (скорее всего это будет PostgreSQL).
Disclaimer
Для остальных кто сюда пришел из поисковых движков, взять очередной готовый биллинг предупреждаю сразу этого тут нет.
Для начала слайды.
По клику доступна версия побольше. Как видите с одной стороны таблиц вроде бы и много, но функционала если подумать мало. Все верно, эта схема хранения, она не отвечает на вопросы как начислить и какие тарифные планы у клиента. В ее функционал входят:
- Договор клиента и ведение его баланса
- Начисление услуг и их стоимость
- Предоставление скидок
- Проведение платежей
- Перевод денежных средств
- Ввод остатков клиента из другой системы
- Счета выставленные клиенту и их погашение
Прежде чем переходить к описанию я укажу те соглашения которые используются во всей схеме:
- Внешние ключи идут в формате 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. Если частично, то остаток. Необходим исключительно из-за того что платеж может покрывать два документа по оплате.
Ну и пожалуй на этом пока все.
Теперь про то что в данный момент не учтено в схеме:
- НДС. Нужны эксперты. Я не совсем в этом эксперт, но что-то мне подсказывает, что только добавлением в таблицу цены (bill.price) еще цены без НДС или с НДС не обойтись.
- Мультивалютность. Не сталкивался в своей работе и не могу сказать насколько это надо и что потребуется для реализации. Основная с моей точки зрения проблема это конвертация. Без нее все проще и удобнее.
PS
После того как тут будут косяки отловлены и проблемы найдены, будет переход ко второй части. Которая уже содержит такой треш и угар как тарифные планы и типы начислений, учет состояния договора и т.п.