forum.bitel.ru
http://forum.bitel.ru/

[feature] Реализация процентных скидок в BG
http://forum.bitel.ru/viewtopic.php?f=16&t=6122
Страница 1 из 2

Автор:  Cromeshnic [ 15 ноя 2011, 09:55 ]
Заголовок сообщения:  [feature] Реализация процентных скидок в BG

1. Типы скидок

Так или иначе, всем приходится сталкиваться с ситуацией, когда некоторые услуги продаются клиенту по индивидуальной цене. В лучшем случае в организации есть бизнес-логика предоставления скидок, в худшем это делается наобум. Если подходить к вопросу системно, то для учёта скидок нужно решить 3 вопроса:
- Политика скидок (кому сколько и при каких условиях)
- Механизм начисления (техническая сторона)
- Отчетность

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

У меня получился такой список:
а) Скидки на подключение (разовые)
б) Фиксированные скидки на периодические услуги (цена минус X р.)
в) Процентные скидки на периодические услуги
г) Индивидуальная цена на услугу
д) Скидка на сумму счета

а) Начисление реализуется либо тупо путём занесения в BG расходов нужной суммы (но тогда пропадает отчетность), либо например двумя расходами: расход со стандартной ценой минус расход другого типа со скидкой. В любом случае, сделать workaround вокруг расходов можно. От биллинга тут ничего не требуется.
б) Выглядит как-то странно, но менеджеры могут придумать и не такое :). Можно тупо завести абонплату "скидка" с ценой в -1р. и вешать на договор с количеством, равным X. Забавно, но работает :) От биллинга тут ничего не требуется.
в) Тут нужна реализация в биллинге, см. ниже.
г) Слишком общая постановка, кроме персональных тарифов ничего не придумаешь. От биллинга тут ничего не требуется.
д) вычисляется только после создания счета => можно реализовать скриптами. От биллинга тут ничего не требуется.

Почему нельзя просто использовать персональные тарифы? За годы их использования имеем следующие проблемы:
- Отсутствует прозрачность (=> контроль) за предоставлением скидок.
- Сложности с внедрением новых тарифов (при введении новых тарифов или изменении старых приходится поддерживать персональные)
- Сложности с построением отчетов по тарифам

Скидка по своей сути - это некая сущность клиентского договора, имеющая период действия и набор параметров, а также влияющая на наработку.

2. Реализация процентных скидок в BGBilling
Т.о. нам нужна некая сущность договора, по которой можно было бы начислять скидки как процент от наработки по другим услугам. Нужно указать: date1, date2, sids (через запятую), % скидки.

Предлагаю следущую схему:
- Скидка - это абонплата, процент указывается в количестве абонплаты:
Вложение:
npays-discount.jpg
npays-discount.jpg [ 35.26 КБ | Просмотров: 31152 ]

- В тарифном плане вместо узла "стоимость" указывается новый тип узла "скидка" (java-код ниже):
Код:
mysql> select * from mtree_node where id=48;
+----+-------------+----------+----------+----------+-----+
| id | parent_node | mtree_id | type     | data     | pos |
+----+-------------+----------+----------+----------+-----+
| 48 |          47 |        3 | discount | sids&5,6 |   0 |
+----+-------------+----------+----------+----------+-----+
1 row in set (0.00 sec)

(5 - услуга 'Доступ в интернет', 6 - услуга 'Доступ в интернет (локальный трафик)')
Вложение:
npays-discount-tariff-tree.jpg
npays-discount-tariff-tree.jpg [ 28.91 КБ | Просмотров: 31152 ]


Узел работает только для месячной абонплаты (для простоты).
В узле discount задаётся список услуг, для которых считается скидка. Услуги можно указывать вообще любые.
Узел возвращает цену абонплаты равной = select -sum(summa)/100 from contract_account where sid in (<sids>) and yy=<yy> and mm=<mm> and cid=<cid>
Т.е. 1% от суммы наработки договора по нужным нам услугам в месяце, за который вычисляем абонплаты.

!!! Важно !!! Узел работает в режиме "безусловно". Т.е. если мы поставили скидочную абонплату в середине месяца, то скидка все равно насчитается как % от наработки по услугам за весь месяц. Иначе нельзя, т.к. наработка по услугам хранится с точностью до месяца. Т.о. скидки предоставляются по месяцам.

Всё просто и удобно :)

Запускаем начисление абонплат и получаем скидку на 15 ноября = 30% * 100р. * (15 дней/30 дней) = 15р.
Вложение:
npays-discount-account.jpg
npays-discount-account.jpg [ 20.53 КБ | Просмотров: 31152 ]


Вот код класса узла [для 5.2]:

Код:
package ru.bitel.bgbilling.modules.npay.tariff.server;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;

import ru.bitel.bgbilling.kernel.tariff.tree.server.DefaultTariffTreeNode;
import ru.bitel.common.ParameterMap;
import ru.bitel.common.Utils;

public class MonthModeDiscountByServicesTariffTreeNode extends DefaultTariffTreeNode<NPayTariffRequest, NPayTariffContext>
{
  private String sids;

  public MonthModeDiscountByServicesTariffTreeNode(int id, ParameterMap parameterMap)
  {
    super(id, parameterMap);

    this.sids = parameterMap.get("sids", "");//список sid-ов через запятую
  }

  protected int executeImpl(Long treeNodeId, NPayTariffRequest req, NPayTariffContext ctx)
  {
   BigDecimal cost = BigDecimal.ZERO;
   //Берем наработку по услугам из 'sids'
   //Не нашел метода в API, чтобы получить наработку по списку услуг без субдоговоров, считаем руками:
   String query =
         "SELECT sum(summa) FROM contract_account WHERE yy=? AND mm=? AND sid IN (" +
         this.sids + ") AND cid=?";
   Connection con = req.getConnection();
   try {
      PreparedStatement ps = con.prepareStatement(query);
      ps.setInt(1, req.getTime().get(Calendar.YEAR));
   
      ps.setInt(2, req.getTime().get(Calendar.MONTH)+1);
      ps.setInt(3, req.cid);
      ResultSet rs = ps.executeQuery();
      if (rs.next())
      {
        cost = Utils.maskNull(rs.getBigDecimal(1)).divide(BigDecimal.valueOf(100)).negate();
      }
      rs.close();
      ps.close();
   } catch (SQLException e) {
      req.addError("Error while obtaining discount service account for sids: "+this.sids+". Node: "+this.fingerprint + ". Error:"+e.getMessage());
      e.printStackTrace();
   }
   req.serviceCost.cost = cost;
   
    return 1;
  }
}


Прописываем в npay.xml:
Код:
          <node type="discount" class1="" title="Discount" class2="ru.bitel.bgbilling.modules.npay.tariff.server.MonthModeDiscountByServicesTariffTreeNode"/>

<!--... -->

          <node type="month_mode" class1="bitel.billing.module.services.npay.MonthCalculateModeTariffTreeNode" title="Iany?iue ?a?ei niyoey" class2="ru.bitel.bgbilling.modules.npay.tariff.server.CalculateModeTariffTreeNode">
                 <node type="month_cost"/>
                 <node type="add_cost"/>
                 <node type="month_period"/>
                 <node type="month_if"/>
                 <node type="month_if_account"/>
                 <node type="mult_cost"/>
                 <node type="month_option"/>
                 <node type="discount"/>
          </node>
           <node type="month_period" class1="bitel.billing.module.tariff.PeriodTariffTreeNode" title="Ia?eia" class2="ru.bitel.bgbilling.kernel.tariff.tree.server.PeriodTariffTreeNode">
                 <node type="month_if"/>
                 <node type="month_cost"/>
                 <node type="month_if_account"/>
                 <node type="mult_cost"/>
                 <node type="month_option"/>
                 <node type="discount"/>
          </node>

           <node type="month_if" class1="bitel.billing.module.services.npay.AmountRangeTariffTreeNode" title="Oneiaea ii iauaio oneoae" class2="ru.bitel.bgbilling.modules.npay.tariff.server.AmountRangeTariffTreeNode">
                <node type="month_period"/>
                <node type="month_cost"/>
                <node type="mult_cost"/>
                <node type="discount"/>
          </node>

<!--... -->

          <node type="month_option" category="directory" class1="ru.bitel.bgbilling.modules.npay.tariff.client.OptionTariffTreeNode" title="Iioey" class2="ru.bitel.bgbilling.modules.npay.tariff.server.OptionTariffTreeNode">
                 <node type="month_cost"/>
                 <node type="add_cost"/>
                 <node type="month_period"/>
                 <node type="month_if"/>
                 <node type="month_if_account"/>
                 <node type="mult_cost"/>
                 <node type="discount"/>
          </node>



Для 5.1 я думаю принципиальных отличий не должно быть.

3. Недостатки
- % скидки может быть только целым
- % скидки нельзя указать отрицательным (продать дороже)

Собственно, вопрос к разработчикам - можете реализовать это официально?

В виде костыля неудобно поьзоваться по двум причинам:
- Лень ковырять клиент, чтобы добиться поддержки отображения и редактирования узла discount
- Приходится переопределять npay.xml в локальной директории => нужно будет следить за его обновлениями

Автор:  skyb [ 15 ноя 2011, 10:05 ]
Заголовок сообщения:  Re: Реализация процентных скидок в BG

Собственно все кул, у меня вопрос возник.
1. Тут заложена логика предоставлении скидки на определенный срок, и где это указать? тоесть с середины следущюего месяца, и оканчивается через 2 месяца.
А так поддерживаю, я чета затупил и выставлял в тарифных планах процент скидки на услугу абонплаты, а не количеством.

Автор:  Cromeshnic [ 15 ноя 2011, 11:07 ]
Заголовок сообщения:  Re: Реализация процентных скидок в BG

skyb, ой кстати есть косяк - скидка при такой реализации будет только с точностью до месяца. Щас подумаю...

Автор:  Cromeshnic [ 15 ноя 2011, 11:36 ]
Заголовок сообщения:  Re: Реализация процентных скидок в BG

Подумал, дописал:

Цитата:
!!! Важно !!! Узел работает в режиме "безусловно". Т.е. если мы поставили скидочную абонплату в середине месяца, то скидка все равно насчитается как % от наработки по услугам за весь месяц. Иначе нельзя, т.к. наработка по услугам хранится с точностью до месяца. Т.о. скидки предоставляются по месяцам.


skyb, по твоему вопросу - период предоставления скидки регулируется периодом действия скидочной абонплаты на договоре, с точностью до месяца.

Автор:  skyb [ 15 ноя 2011, 12:48 ]
Заголовок сообщения:  Re: Реализация процентных скидок в BG

Cromeshnic писал(а):
Подумал, дописал:

Цитата:
!!! Важно !!! Узел работает в режиме "безусловно". Т.е. если мы поставили скидочную абонплату в середине месяца, то скидка все равно насчитается как % от наработки по услугам за весь месяц. Иначе нельзя, т.к. наработка по услугам хранится с точностью до месяца. Т.о. скидки предоставляются по месяцам.


skyb, по твоему вопросу - период предоставления скидки регулируется периодом действия скидочной абонплаты на договоре, с точностью до месяца.

С точностью до календарного месяца или абонентского?

Автор:  Cromeshnic [ 15 ноя 2011, 12:52 ]
Заголовок сообщения:  Re: Реализация процентных скидок в BG

Календарного конечно, где ты видел в биллинге абонентский месяц? :)

Автор:  skyb [ 15 ноя 2011, 13:01 ]
Заголовок сообщения:  Re: Реализация процентных скидок в BG

Cromeshnic писал(а):
Календарного конечно, где ты видел в биллинге абонентский месяц? :)

малоли =), эх, несовсем универсально, было бы круто если бы ещё по любым датам можно было скидку давать на эти дни

Автор:  Cromeshnic [ 15 ноя 2011, 13:41 ]
Заголовок сообщения:  Re: Реализация процентных скидок в BG

Есть ещё нюанс - если запускаем обсчет абонплат первый раз за день и скидки считаются от других абонплат, то они рассчитаются по данным только на предыдущий день. Поэтому для верности пересчет нужно запускать два раза подряд - скажем, перед массовым выставлением счетов.

Автор:  Cromeshnic [ 16 ноя 2011, 08:34 ]
Заголовок сообщения:  Re: Реализация процентных скидок в BG

Тема скидок уже всплывала:
viewtopic.php?f=22&t=5907
summon SafeAndSound
:)

Автор:  Cromeshnic [ 17 ноя 2011, 11:29 ]
Заголовок сообщения:  Re: Реализация процентных скидок в BG

До кучи:
viewtopic.php?f=1&t=1215
viewtopic.php?f=5&t=5899

Автор:  Cromeshnic [ 28 ноя 2011, 09:05 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

Я не понял, никому уже не интересно? Или я мудрено написал? :)

Как вариант, можно вынести эту логику в отдельный модуль. Тогда и список услуг, на которые вешается скидка, можно указывать прямо в сущности договора этого модуля.

Автор:  skyb [ 28 ноя 2011, 12:44 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

Cromeshnic писал(а):
Я не понял, никому уже не интересно? Или я мудрено написал? :)

интересно, просто у меня немного другая логика скидок и несовсем эта подойдет :(

Автор:  Cromeshnic [ 28 ноя 2011, 13:20 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

Опиши, может придумаем общее решение.

Автор:  vdd [ 13 дек 2011, 17:13 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

Пролетала как-то идея "скриптовых" тарифов, как более общая альтернатива скидкам и бонусам.
Непосредственно по скидкам: Скидка - частный случай бонуса. Может быть переключится на бонусы?

Автор:  Cromeshnic [ 14 дек 2011, 06:39 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

С бонусами непонятно толком, как их можно реализовать.
viewtopic.php?p=46550#p46550

А скидки мне нужны как замена персональным тарифам.

Автор:  vdd [ 14 дек 2011, 12:08 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

Cromeshnic писал(а):
С бонусами непонятно толком, как их можно реализовать.
viewtopic.php?p=46550#p46550

А скидки мне нужны как замена персональным тарифам.


Цитата:
помоему не должно быть "Виртуальных платежей", бонусы должны давать скидку на услугу (т.е. изменять ее стоимость вплоть до нуля).
и минимум двое согласных с этим.

Это из обсуждения по ссылке. :wink:

IMHO: нас спасут либо "скриптовые" тарифы, либо возможность создать модуль, добавляющий свои пять копеек в тарифное дерево.

Автор:  Cromeshnic [ 14 дек 2011, 15:07 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

Можно развить идею в первом посте.

Например, сделать модуль "Скидки/бонусы".
* Скидки реализовать по схеме из первого поста: "скидка" - это сущность модуля на договоре с периодом действия и %, наработка по ней будет отрицательной, в процентах от суммарной наработки по набору услуг других модулей.
* Бонусы. Допустим для модуля заведены услуги "Бонус на инет", "Бонус на локальный трафик".
В модуле ведётся помесячный баланс по этим услугам : bonus_balance_<mid> (cid, yy, mm, sid, summa1, summa2)
summa1 - вх баланс бонуса sid на договоре cid за yy, mm
summa2 - суммарные поступления бонуса за месяц. Поступления делаются через интерфейс клиента и в скриптах - у каждого своя логика их начисления. Детально поступления попадают в bonus_payment_<mid> (...)
Растрат бонуса в таблице нет осознанно - они берутся из contract_account. Расходов тоже нет - можно сделать отрицательными приходами, здесь большой разницы нет.

В тарифной ветке модуля всего 2 новых узла: "тарифицировать скидку" и "тарифицировать бонус"
"Тарифицировать скидку" - указывается sid скидки и список sid-ов услуг, % от которых она вычисляет. Узел возвращает цену в -1% от суммарной наработки по услугам за месяц. Количество процентов указывается в сущности "скидка" договора. Наработка идёт в указанный sid услуги-скидки.
"Тарифицировать бонус" - указывается sid бонуса и список sid-ов услуг, по которым он считается. Узел возвращает стоимость в -min(<текущий баланс бонуса>, <сумма наработки по указанным услугам>). Наработка идёт в указаный sid услуги-бонуса.

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

Например, у клиента на бонусном счету имеется:
50р. бонуса "Бонус на инет" (sid=1) и 100р. - "Бонус на локальный трафик" (sid=2)
Наработка:
"Инет-абонплата" (sid=3) = 40р.
"Инет-вх трафик" (sid=4) = 30р.
"Инет-вх локальный трафик" (sid=5) = 20р.

В тарифе:
Код:
*<Модуль "Бонусы и скидки">
 |
  *<Тарифицировать бонус sid=1 по услугам: 3,4>
 |
  *<Тарифицировать бонус sid=2 по услугам: 5>


Тогда:
наработка в contract_account по услуге sid=1 будет = -50р. ( =-min(50, 40+30) )
наработка в contract_account по услуге sid=2 будет = -20р. ( =-min(100, 20) )

На следующий месяц перейдет 80р. бонуса за локальный трафик (sid=2)

зы.
Начисление бонусов каждый реализует сам.

ззы.
Почему именно отрицательной наработкой по другим услугам? Мне кажется, так проще и нагляднее. Если делать универсальный механизм "урезания" наработки по произвольной услуге, это должна быть новая прослойка в ядре на уровне contract_account.

Автор:  vdd [ 14 дек 2011, 16:21 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

Бонусы опять в рублях?

Автор:  skyb [ 14 дек 2011, 16:49 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

vdd писал(а):
Бонусы опять в рублях?

в еденицах

Автор:  Cromeshnic [ 15 дек 2011, 06:38 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

Ну тут в рублях.
Предложите свой сценарий.

Автор:  Cromeshnic [ 19 янв 2012, 07:06 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

Пример использования % скидок:
http://www.is74.ru/home/internet/tariffs/addons/

Автор:  Universe [ 25 янв 2012, 15:03 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

Как вариант реализации Бонусов мы сейчас используем, как тут говорилось, "виртуальные платежи", правда в рублях, а не попугаях.
При поступлении на счёт абонента разовой суммы более Х руб. (за минусом долга на первое число) отдельным типом платежа на счёт падает Бонус хх%. (При поступлении суммы более Y руб. - Бонус yy%).
Проблем с начислением абон.платы и отчётностью не возникает, да и персональные тарифы не требуются.
Реализовано это скриптом, добавленным на каждый договор.
Скидки не используем.

Автор:  skyb [ 25 янв 2012, 15:59 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

Universe писал(а):
Как вариант реализации Бонусов мы сейчас используем, как тут говорилось, "виртуальные платежи", правда в рублях, а не попугаях.

а бухгалтерия не против? этож запрещено, я и ссыль кидал, завтра таки доберусь до темы

Автор:  snark [ 25 янв 2012, 16:05 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

А разве бухгалтерии обязательно показывать все деньги?
Реальные деньги они показывают, а всякие компенсационные, бонусные и прочие "нереальные" (реального бабла там - тока цифры) платежи - не обязательно.

Автор:  Universe [ 25 янв 2012, 16:52 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

snark писал(а):
А разве бухгалтерии обязательно показывать все деньги?
Реальные деньги они показывают, а всякие компенсационные, бонусные и прочие "нереальные" (реального бабла там - тока цифры) платежи - не обязательно.


Совершенно верно. Никаких проблем нет. В отчёте выбираю, только "реальные" платежи. Которые затем и делятся на все подключенные услуги.
Учитывая, что Интернет безлимитный и строгой отчётности не требуется, то бухгалтерия не против.
Так как Бонус - это отдельный тип платежа, по нему тоже всегда можно сделать дополнительный отчёт.

Автор:  skyb [ 25 янв 2012, 17:38 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

snark писал(а):
А разве бухгалтерии обязательно показывать все деньги?
Реальные деньги они показывают, а всякие компенсационные, бонусные и прочие "нереальные" (реального бабла там - тока цифры) платежи - не обязательно.

вот реально лень искать по форуму про это, но нельзя добавлять платеж фейковый на учетку, он должен быть в любом случае реален, поищи по форуму, уже обсуждалось давно....

Автор:  snark [ 25 янв 2012, 19:51 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

Все зависит от того что именно считается реальным платежом, а что фейковым.
Реальный == настоящие, живые деньги.
Фейковый == все что не "реальный", например компенсация % при платеже через mps.

Автор:  skyb [ 26 янв 2012, 06:00 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

snark писал(а):
Все зависит от того что именно считается реальным платежом, а что фейковым.
Реальный == настоящие, живые деньги.
Фейковый == все что не "реальный", например компенсация % при платеже через mps.

viewtopic.php?p=7178#p7178
blib писал(а):
если следовать букве закона то да можно, но если ВЫ платите деньги физическому лицу то вы должны считать подоходный налог + ЕСН.

это если быть до конца честными...
поэтому это по бугалтерии проходит как скидка ! а не как выплаты клиенту, по бугалтерии вы просто ему услуги дешевле продаете а не даете ему деньги.

Автор:  Cromeshnic [ 26 янв 2012, 07:26 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

2 Universe, а синхранизация с 1с у вас есть какая-нибудь? Наработка, баланс, платежи, расходы? У нас например четко должен совпадать баланс на конец месяца в биллинге и 1C. Если у вас автоматизированно оно не ведётся, как вы отслеживаете нестыковки? Например, в биллинге есть платеж / расход / наработка по услуге, а в 1С - нет. Или наоборот. Или в 1С у вас не ведутся абонентские договоры, только общая движуха денег?

Автор:  Cromeshnic [ 26 янв 2012, 07:27 ]
Заголовок сообщения:  Re: [feature] Реализация процентных скидок в BG

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

Страница 1 из 2 Часовой пояс: UTC + 5 часов [ Летнее время ]
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/