forum.bitel.ru http://forum.bitel.ru/ |
|
Определение сложной абонплаты (BGBS) http://forum.bitel.ru/viewtopic.php?f=19&t=2051 |
Страница 1 из 1 |
Автор: | lda [ 19 мар 2009, 12:30 ] |
Заголовок сообщения: | Определение сложной абонплаты (BGBS) |
Доброго времени суток. Есть задача. Необходимо определить из скрипта BGBS параметры тарификации абонплаты, таких как: 1. Тарификация идет за день или за месяц. 2. Размер абонплаты. 3. и т. д. Тариф для абонплаты может быть сложный. Привожу несколько примеров. В wiki есть пример определения абонплаты "Определение размера абонентской платы", но он работает только на примере1, для двух других вариантов он не работает, да и дает он не полную информацию. Через SQL эту задачу реализовал, но хотелось бы сделать через классы и методы API. Прошу помочь. |
Автор: | Администратор [ 19 мар 2009, 16:26 ] |
Заголовок сообщения: | |
Выложите хоть, что писали, что получили и чего не хватает.. |
Автор: | lda [ 19 мар 2009, 17:03 ] |
Заголовок сообщения: | |
Вот такой вот сырой вариант: Код: private getCost(parent_node)
{ query_get_cost = "SELECT type, data FROM mtree_node WHERE parent_node='"+parent_node+"'"; re_get_cost = con.prepareStatement(query_get_cost); ResultSet re_get_cost = re_get_cost.executeQuery(); while (re_get_cost.next()) { type = re_get_cost.getString(1); data = re_get_cost.getString(2); type_cost = "0"; cost = "0"; if (type.indexOf("day_cost") == -1 && type.indexOf("month_cost") == -1) { print (type); error( "Ошибка в логике работы скрипта" ); return null; }; String[] arr = data.split ("%"); if (arr.length == 2){ String[] arr_type = arr[0].split ("&"); String[] arr_cost = arr[1].split ("&"); if (arr_type.length == 2) { type_cost = arr_type[1]; }; if (arr_cost.length == 2) { cost = arr_cost[1]; }; }; if (type.indexOf("month_cost") != -1 && type_cost.indexOf("1") != -1) { return "month_cost%"+cost; } else if(type.indexOf("day_cost") != -1 && cost.indexOf("0") != -1) { return "day_cost%"+cost; } else { error( "Неверный тариф" ); return null; }; } return null; } private getAbnCost( cid, date_curr ) { query = " SELECT mtree_node.id, mtree_node.parent_node, mtree_node.mtree_id " + " FROM contract_tree_link"+ " INNER JOIN (module_tariff_tree"+ " INNER JOIN mtree_node"+ " ON (module_tariff_tree.id=mtree_node.mtree_id))"+ " ON (contract_tree_link.tree_id=module_tariff_tree.tree_id)"+ " WHERE (contract_tree_link.date1 is NULL OR contract_tree_link.date1<='"+date_curr+"') AND"+ " (contract_tree_link.date2 is NULL OR contract_tree_link.date2>='"+date_curr+"')"+ " AND contract_tree_link.cid='"+cid+"' AND module_tariff_tree.mid='7'"+ " AND mtree_node.type IN ('day_mode', 'month_mode') AND mtree_node.data IN ('sid&23%type&1%mode&day', 'sid&23%mode&month')"+ " UNION"+ " SELECT mtree_node.id, mtree_node.parent_node, mtree_node.mtree_id"+ " FROM contract_tariff"+ " INNER JOIN (tariff_tree_link"+ " INNER JOIN (module_tariff_tree"+ " INNER JOIN mtree_node"+ " ON (module_tariff_tree.id=mtree_node.mtree_id))"+ " ON (tariff_tree_link.tree_id=module_tariff_tree.tree_id))"+ " ON (contract_tariff.tpid=tariff_tree_link.tpid)"+ " WHERE (contract_tariff.date1 is NULL OR contract_tariff.date1<='"+date_curr+"') AND"+ " (contract_tariff.date2 is NULL OR contract_tariff.date2>='"+date_curr+"')"+ " AND contract_tariff.cid='"+cid+"' AND module_tariff_tree.mid='7'"+ " AND mtree_node.type IN ('day_mode', 'month_mode') AND mtree_node.data IN ('sid&23%type&1%mode&day', 'sid&23%mode&month')"; re = con.prepareStatement(query); ResultSet re = re.executeQuery(); while (re.next()) { node_id = re.getString(1); parent_node = re.getString(2); mtree_id = re.getString(3); Skip = false; //проверяем предыдущий параметр, возможно это период query_check_prev_date = "SELECT type, data FROM mtree_node WHERE id='"+parent_node+"'"; re_check_prev_date = con.prepareStatement(query_check_prev_date); ResultSet re_check_prev_date = re_check_prev_date.executeQuery(); while (re_check_prev_date.next()) { prev_date1 = null; prev_date2 = null; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); date_ = sdf.parse(date_curr); type = re_check_prev_date.getString(1); data = re_check_prev_date.getString(2); if (type.indexOf("global_period") != -1) { String[] dates = data.split ("%"); if (dates.length == 2) { String[] dates1 = dates[1].split ("&"); String[] dates2 = dates[0].split ("&"); if (dates1.length == 2) { SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyy"); prev_date1 = sdf.parse(dates1[1]); }; if (dates2.length == 2) { SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyy"); prev_date2 = sdf.parse(dates2[1]); }; }; if (prev_date1 != null && prev_date1.compareTo(date_) == 1) { Skip = true; }; if (prev_date2 != null && prev_date2.compareTo(date_) == -1) { Skip = true; }; }; }; if (Skip) { continue; }; //проверяем следующий параметр, возможно это период query_check_date = "SELECT id, parent_node, mtree_id, type, data FROM mtree_node WHERE parent_node='"+node_id+"'"; re_check_date = con.prepareStatement(query_check_date); ResultSet re_check_date = re_check_date.executeQuery(); Skip = true; while (re_check_date.next()) { date1 = null; date2 = null; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); date_ = sdf.parse(date_curr); node_id_ = re_check_date.getString(1); parent_node_ = re_check_date.getString(2); mtree_id_ = re_check_date.getString(3); type = re_check_date.getString(4); data = re_check_date.getString(5); if (type.indexOf("day_period") != -1 || type.indexOf("month_period") != -1) { String[] dates = data.split ("%"); if (dates.length == 2) { String[] dates1 = dates[1].split ("&"); String[] dates2 = dates[0].split ("&"); if (dates1.length == 2) { SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyy"); date1 = sdf.parse(dates1[1]); }; if (dates2.length == 2) { SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyy"); date2 = sdf.parse(dates2[1]); }; }; if ((date1 == null || date1.compareTo(date_) == -1) && (date2 == null || date2.compareTo(date_) == 1)) { Skip = false; node_id = node_id_; parent_node = parent_node_; mtree_id = mtree_id_; break; }; } else { Skip = false; break; }; }; if (Skip ) { continue; }; Cost = getCost(node_id); if (Cost != null) { return Cost; }; }; return null; } date_str=TimeUtils.format(date, "yyyy-MM-dd"); Cost_data = getAbnCost(cid,date_str); if (Cost_data == null) { //пропускаем тех у кого не найдена необходимая абонплата return; }; Cost_arr = Cost_data.split ("%"); cost_type = Cost_arr[0]; cost = Double.parseDouble(Cost_arr[1]); day_str=TimeUtils.format(date, "dd"); day = Double.parseDouble(day_str); if ((cost_type.indexOf("day_cost") == -1 && cost_type.indexOf("month_cost") == -1) || (cost_type.indexOf("month_cost") != -1 && day != 1)) { return; }; Функция getAbnCost выбирает из глобальных и персональных тарифов все узлы где описывается услуга 23 (mtree_node.data IN ('sid&23%type&1%mode&day', 'sid&23%mode&month')), проверяет есть ли до этого узла или после него узел типа "период" и обрабатывает его. На выходе имею <тип тарификации(за день или за месяц)>%<стоимость>. Эта функция часть предполагаемой логики по блокировки пользователей. Скрипт будет запускаться в начале дня до списания абонплаты и блокировать тех у кого недостаточно денег на счету. Абоненты, у которых абонплата списывается за месяц будет проверяться первого числа, а у которых за день, то каждый день. В общем то я получил все, что мне необходимо. Меня беспокоит то, что при изменении структуры базы эта функция работать не будет. Хотелось бы привязаться к вашему API, и код будет попроще и работать будет побыстрее. |
Автор: | Администратор [ 19 мар 2009, 18:21 ] |
Заголовок сообщения: | |
Что вы делали через API и что там не получилось? |
Автор: | lda [ 19 мар 2009, 18:50 ] |
Заголовок сообщения: | |
Делал так (пример из wiki): Код: // код договора
cid = event.getContractID(); // на какой момент смотреть тариф time = new GregorianCalendar(); // код услуги sid = 23; // код экземпляра модуля mid = 7; tts = new ContractManager( con ).getRealtimeTariffTreeSet( cid, time, "npay", mid, true ); // перебор тарифов в порядке позиций сначала персональных, потом глобальных for( TariffModuleTree tree : tts.getTreeList( time ) ) { req = new TariffRequest(); req.setRequestParam( "action", "calculate" ); req.setRequestParam( "sid", sid ); // считаем как будто абонплата подключена весь месяц req.setRequestParam( "month_days", 1 ); req.setRequestParam( "period_days", 1 ); tree.processRequest( req ); cost = (Double)req.getResponseParam( "cost" ); if( req.wasAccepted() && cost != null ) { print( cost ); break; } } Не получилось определить размер абонплаты для "Пример2" и "Пример3" (см. начало) Не получилось определить тип абонплаты. Необходимо узнать как снимается абонплата, за день или за месяц. |
Автор: | Администратор [ 19 мар 2009, 18:55 ] |
Заголовок сообщения: | |
Так можно узнать тип абонплаты: Код: TariffRequest req = new TariffRequest(); req.setRequestParam( "action", "reset" ); req.setRequestParam( "sid", item.sid ); req.setRequestParam( "time", item.date1 ); ... String calcMode = (String)req.getResponseParam( "calc_mode" ); В вашем случае, чтобы узнать цену, нужно передать объект типа GregorianCalendar: Код: req.setRequestParam( "time", item.date2 );
Только для подневного режима цена возвращается одного дня, в оригинале тарификатор делает запрос на каждый день. |
Автор: | lda [ 19 мар 2009, 19:30 ] |
Заголовок сообщения: | |
Код: req.setRequestParam( "time", time); Это работает, "период" учитывается. А вот Код: (String)req.getResponseParam( "calc_mode" ); всегда возвращает null. Делал так: Код: // код договора
cid = event.getContractID(); // на какой момент смотреть тариф time = new GregorianCalendar(); // код услуги sid = 23; // код экземпляра модуля mid = 7; tts = new ContractManager( con ).getRealtimeTariffTreeSet( cid, time, "npay", mid, true ); // перебор тарифов в порядке позиций сначала персональных, потом глобальных for( TariffModuleTree tree : tts.getTreeList( time ) ) { req = new TariffRequest(); req.setRequestParam( "action", "calculate" ); req.setRequestParam( "sid", sid ); // считаем как будто абонплата подключена весь месяц req.setRequestParam( "month_days", 1 ); req.setRequestParam( "period_days", 1 ); req.setRequestParam( "time", time); tree.processRequest( req ); cost = (Double)req.getResponseParam( "cost" ); calcMode = (String)req.getResponseParam( "calc_mode" ); print( calcMode ); } |
Автор: | lda [ 23 мар 2009, 13:05 ] |
Заголовок сообщения: | |
Как получить calc_mode? |
Автор: | Администратор [ 23 мар 2009, 16:48 ] |
Заголовок сообщения: | |
Просто повторите код, который я вам дал. Там 2 типа запроса: выяснение типа и выяснянение цены. |
Автор: | lda [ 23 мар 2009, 17:03 ] |
Заголовок сообщения: | |
Невнимательно посмотрел. Все получилось, спасибо! |
Автор: | snark [ 15 фев 2010, 20:39 ] |
Заголовок сообщения: | Re: Определение сложной абонплаты (BGBS) |
можете показать результат? а то у меня не получается вот такой скрипт: Код: import bitel.billing.server.contract.bean.*; import bitel.billing.server.script.bean.event.*; import bitel.billing.server.tariff.*; import bitel.billing.server.util.*; import java.sql.*; import java.util.*; // код договора cid = event.getContractID(); // на какой момент смотреть тариф time = new GregorianCalendar(); // код услуги sid = 9; // код экземпляра модуля mid = 3; tts = new ContractManager( con ).getRealtimeTariffTreeSet( cid, time, "npay", mid, true ); // перебор тарифов в порядке позиций сначала персональных, потом глобальных for( TariffModuleTree tree : tts.getTreeList( time ) ) { req = new TariffRequest(); req.setRequestParam( "action", "calculate" ); req.setRequestParam( "sid", sid ); // считаем как будто абонплата подключена весь месяц req.setRequestParam( "month_days", 1 ); req.setRequestParam( "period_days", 1 ); req.setRequestParam( "time", time); tree.processRequest( req ); cost = (Float)req.getResponseParam( "cost" ); print( cost ); } выдает это: Код: # cat script.log | grep ERROR
2010-02-15 15:32:28,080 ERROR [pool-2-thread-6] LoggingPrintStream - java.io.IOException: Stream closed 2010-02-15 15:32:28,080 ERROR [pool-2-thread-6] LoggingPrintStream - at java.io.BufferedInputStream.getInIfOpen(BufferedInputStream.java:134) 2010-02-15 15:32:28,080 ERROR [pool-2-thread-6] LoggingPrintStream - at java.io.BufferedInputStream.fill(BufferedInputStream.java:218) 2010-02-15 15:32:28,080 ERROR [pool-2-thread-6] LoggingPrintStream - at java.io.BufferedInputStream.read1(BufferedInputStream.java:258) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at java.io.BufferedInputStream.read(BufferedInputStream.java:317) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.common.CommonUtils.readByBlock(CommonUtils.java:896) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.tariff.TariffTreeBuilder.getModuleTariffConfig(TariffTreeBuilder.java:33) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.tariff.TariffModuleTree.init(TariffModuleTree.java:78) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.tariff.TariffModuleTree.load(TariffModuleTree.java:34) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.tariff.TariffTreeSet.getModuleTree(TariffTreeSet.java:48) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.tariff.TariffTreeSet.addTariffTree(TariffTreeSet.java:70) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.contract.bean.ContractManager.getRealtimeTariffTreeSet(ContractManager.java:544) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.contract.bean.ContractManager.getRealtimeTariffTreeSet(ContractManager.java:497) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at java.lang.reflect.Method.invoke(Method.java:597) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bsh.Reflect.invokeMethod(Unknown Source) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bsh.Reflect.invokeObjectMethod(Unknown Source) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bsh.BSHPrimarySuffix.doName(Unknown Source) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bsh.BSHPrimarySuffix.doSuffix(Unknown Source) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bsh.BSHPrimaryExpression.eval(Unknown Source) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bsh.BSHPrimaryExpression.eval(Unknown Source) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bsh.BSHAssignment.eval(Unknown Source) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bsh.Interpreter.eval(Unknown Source) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at ru.bitel.bgbilling.kernel.script.server.bean.ScriptInstance.eval(ScriptInstance.java:310) 2010-02-15 15:32:28,081 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.script.bean.ScriptMachine$SimpleScriptRunner.runScript(ScriptMachine.java:69) 2010-02-15 15:32:28,082 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.script.bean.ScriptMachine.runScriptImpl(ScriptMachine.java:189) 2010-02-15 15:32:28,082 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.script.bean.ScriptMachine.runScript(ScriptMachine.java:128) 2010-02-15 15:32:28,082 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.script.bean.event.EventProcessor.processEvent(EventProcessor.java:227) 2010-02-15 15:32:28,082 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.processor.DefaultProcessor.standartAuth(DefaultProcessor.java:207) 2010-02-15 15:32:28,082 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.processor.dialup.DialUpProcessor.authenticationProcess(DialUpProcessor.java:130) 2010-02-15 15:32:28,082 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.radius.RadiusRequestThread.processRequest(RadiusRequestThread.java:180) 2010-02-15 15:32:28,082 ERROR [pool-2-thread-6] LoggingPrintStream - at bitel.billing.server.radius.RadiusRequestThread.run(RadiusRequestThread.java:79) 2010-02-15 15:32:28,082 ERROR [pool-2-thread-6] LoggingPrintStream - at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885) 2010-02-15 15:32:28,082 ERROR [pool-2-thread-6] LoggingPrintStream - at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907) 2010-02-15 15:32:28,082 ERROR [pool-2-thread-6] LoggingPrintStream - at java.lang.Thread.run(Thread.java:619) |
Автор: | lda [ 16 фев 2010, 12:18 ] |
Заголовок сообщения: | Re: Определение сложной абонплаты (BGBS) |
Посмотрите тут: http://wiki.bgbilling.ru/index.php/%D0% ... 0%B0%D1%85 |
Автор: | snark [ 16 фев 2010, 17:23 ] |
Заголовок сообщения: | Re: Определение сложной абонплаты (BGBS) |
я смотрел ... я всю wiki перерыл и что только не пробывал, но что-то ни в какую у меня не хочет работать в скрипте радиус аутентификации (я хочу не пускать в инет если не хватает денег на абон. плату)? все время выдает ошибку java.io.IOException |
Автор: | lda [ 16 фев 2010, 17:57 ] |
Заголовок сообщения: | Re: Определение сложной абонплаты (BGBS) |
snark писал(а): я смотрел ... я всю wiki перерыл и что только не пробывал, но что-то ни в какую у меня не хочет работать в скрипте радиус аутентификации (я хочу не пускать в инет если не хватает денег на абон. плату)? все время выдает ошибку java.io.IOException кажется я знаю в чем у вас проблема. Дело в том, что скрипт у вас выполняет радиус сервер, а у нас сервер биллинга. У вас радиус сервер не находит какой то библиотеки. Рекомендую вам не пытаться определять размер абонплаты в событии "радиус аутентификация", так как это лишняя нагрузка на радиус. Попробуйте найти другое решение вашей задачи. Например мы блокируем пользователей, у которых недостаточно средств на списание абонплаты и заносим их в специальную группу. |
Автор: | snark [ 16 фев 2010, 19:23 ] |
Заголовок сообщения: | Re: Определение сложной абонплаты (BGBS) |
я уже тоже так подумал, тем более что есть грустный опыт того что радиус не все видит (отсюда и далее) ... наверное буду приостанавливать договора сервером ... |
Страница 1 из 1 | Часовой пояс: UTC + 5 часов [ Летнее время ] |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |