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

Свой action в личном кабинете
http://forum.bitel.ru/viewtopic.php?f=19&t=3230
Страница 1 из 3

Автор:  lda [ 24 ноя 2009, 12:53 ]
Заголовок сообщения:  Свой action в личном кабинете

Биллинг вер. 4.6

Появилась необходимость добавить свой action в личный кабинет пользователя(Web интерфейс).
На форуме нигде полного решения я не нашел. Хотелось бы собрать все воедино.

Редактируем файл /BGBillingServer/webroot/xsl/main.xsl

Добавляем:
...
<xsl:when test="data/@action = 'MemoTable' or data/@action = 'Memo'">ПРИМЕЧАНИЯ</xsl:when>
<xsl:when test="data/@action = 'test'">TEST</xsl:when>
<xsl:otherwise>НОВОСТИ</xsl:otherwise>
...
...
<xsl:when test="@action = 'MemoTable' or @action = 'Memo'">
<xsl:call-template name="Memo"/>
</xsl:when>
<xsl:when test="@action = 'test'">
<xsl:call-template name="Test"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="news"/>
</xsl:otherwise>
...
...
<xsl:otherwise>
<div class="toList"><a href="{$WEBEXECUTER}?action=MemoTable&amp;mid=contract">К списку ...</a></div>
<div class="MemoDate"><!-- <span>Дата:</span> --><xsl:value-of select="/data/memo/@date"/></div>
<div class="MemoTitle"><span>Заголовок:</span> <xsl:value-of select="/data/memo/@title"/></div>
<pre class="MemoText"><xsl:value-of select="/data/memo/@comment"/></pre>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template name="Test">
<select name="test">
<option value="-1">---</option>
<xsl:for-each select="/data/test/table/row">
<option value="{@id}"><xsl:value-of select="@title"/></option>
</xsl:for-each>
</select>
</xsl:template>

<xsl:template name="news">
<xsl:if test="/data/news/item">
<div id="idDivNews">
<xsl:for-each select="/data/news/item">
<span class="date"><xsl:value-of select="@date"/></span><strong class="newsTitle"><xsl:value-of select="@title"/></strong><br/>^M
<xsl:choose>^M
<xsl:when test="data"><xsl:for-each select="data"><xsl:copy-of select="*|text()"/></xsl:for-each></xsl:when>^M
<xsl:otherwise><xsl:for-each select="div"><xsl:value-of select="."/><br/></xsl:for-each></xsl:otherwise>^M
</xsl:choose>
<br/>
</xsl:for-each>
</div>
</xsl:if>
</xsl:template>
...



Пишем пакет (файл WebAction_test.java):
Код:
package bitel.billing.server.contract;

import java.sql.SQLException;
import java.util.List;

import org.w3c.dom.Element;

import bitel.billing.server.contract.action.ActionBase;

public class WebAction_test   extends ActionBase
{
    @Override
    public void doAction()
            throws SQLException
    {
        Element test = createElement( rootNode, "test" );
        Element table = createElement( test, "table" );

        Element element = createElement( table, "row" );
        element.setAttribute( "id", String.valueOf( 1 ) );
        element.setAttribute( "title", "title1" );

        element = createElement( table, "row" );
        element.setAttribute( "id", String.valueOf( 2 ) );
        element.setAttribute( "title", "title2" );
    };
};


Компилим его:
BGBillingServer# /usr/lib/jdk/bin/javac -cp ./:lib/* lda/WebAction_test.java
Получаем файл: WebAction_test.class

Теперь вопрос куда его запихать?
В голову пришло три варианта:
1. Создать ремапинг action.remap_<module>_<action>=mypackage.MyAction
2. Создать отдельную библиотеку(что то вроде test.jar) и положить его в папку lib биллинга
3. Закинуть его в server.jar(/bitel/billing/server/contract)

Я выбрал 3-й вариант, как самый простой, но неверное не самый правильный :)

Я получил то что хотел. В личном кабинете появился пункт меню "TEST". При выборе этого пункта открывается заполненный комбобокс.

У меня вопрос к разработчикам.
Подскажите как правильно добавлять action? Т.е. как правильно подключить WebAction_test.class?

Автор:  Amir [ 24 ноя 2009, 14:09 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Создать отдельную my.jar, потому что иначе при апдейте перетрётся.
Класс в том же пакете что и стандартные веб-экшны.

Автор:  lda [ 24 ноя 2009, 14:24 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Ок. Спасибо.
Извините за глупый вопрос. А как с линуксе создать my.jar? :)
Точнее с какими параметрами запускать /usr/lib/jdk/bin/jar?

Автор:  Amir [ 24 ноя 2009, 14:39 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

jar cf my.jar lda/

Автор:  lda [ 24 ноя 2009, 15:03 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Спасибо. Все получилось.

Автор:  DDPaul [ 21 дек 2009, 13:55 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

А каким образом можно данные из личного кабинета передать в action?
Например, я хочу, чтобы пользователь имел возможность сменить контактный email (аналогично смене пароля).

Автор:  stark [ 21 дек 2009, 16:18 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

DDPaul писал(а):
А каким образом можно данные из личного кабинета передать в action?
Например, я хочу, чтобы пользователь имел возможность сменить контактный email (аналогично смене пароля).

данные передаются как стандартные параметры запроса ,а actiop достает их запроса ( объект request ) по имени

Автор:  DDPaul [ 21 дек 2009, 17:41 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

А какой класс нужно использовать для работы с объектом request? Я пока не слишком силен в Java :)

Автор:  stark [ 21 дек 2009, 19:11 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

DDPaul писал(а):
А какой класс нужно использовать для работы с объектом request? Я пока не слишком силен в Java :)

если вы пишете свой Action, знаит он наследуется от bitel.billing.server.ActionBase и там есть уже поле request - оно доступно

Автор:  DDPaul [ 21 дек 2009, 20:31 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Понял, спасибо, работает.

Еще пара вопросов.

1. Как в action'е добавить новый атрибут к xml-узлу data?
Например, атрибут status="ok", так чтобы в шаблонах можно было использовать стандартную конструкцию:
Код:
<xsl:if test="@status = 'ok'"><div class="infoMessage">Email изменен />!</div></xsl:if>

2. Доступна ли API документация по ActionBase?

Автор:  dimOn [ 21 дек 2009, 20:50 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

статус OK сам должен добавиться. статус error устанавливается после setErrorStatus("текст ошибки")

Автор:  dimOn [ 21 дек 2009, 20:51 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

добавить новый атрибут к узлу data:
Код:
rootNode.setAttribute("attr","value");

Автор:  DDPaul [ 23 дек 2009, 13:53 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Спасибо, с этим разобрался.

Теперь вопрос, как, собственно, изменить параметр договора типа email в action'е. Насколько я понимаю, есть 2 способа: через SQL либо через API.

Решил сначала попробовать через API:

Код:
...
String email = request.getParameter( "email" );
   
// Получаем идентификатор клиента в cid, как описано в wiki
// ID параметра типа email - pid

ContractEmailParamValue emailParam = new ContractEmailParamValue();
emailParam.setEmail( email );
    
ContractParameterManager cpm = new ContractParameterManager( con );
cpm.setEmailParam( cid, pid, emailParam, true, 1 );
...


В server.log после запуска action'а видим:
Код:
LoggingPrintStream - com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '12-19' for key 2

cid=12, pid=19 в данном случае.

setEmailParam, насколько я понял, используется для создания нового параметра типа email. А как изменить уже существующий? Удалить и создать или есть специальная функция?

Автор:  DDPaul [ 25 дек 2009, 21:31 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Вроде разобрался, действительно, сначала нужно удалить конкретное значение параметра из договора, потом задать новое, примерно вот так:

Код:
cpm.deleteParamForContract( "contract_parameter_type_3", cid );
cpm.setEmailParam( cid, pid, emailParam, false, 1 );


Пока не понял, как сделать так, чтобы отображаемое в личном кабинете значение изменялось соответственно - видимо генерируемый XML с параметрами договора как-то кэшируется, и измененное значение параметра появляется в ЛК только после перезапуска биллинга. Есть ли тут какое-нибудь решение?

И еще один вопрос - можно ли в action'е вызывать функции из библиотеки скриптов?

Автор:  skn [ 25 дек 2009, 23:19 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

DDPaul писал(а):
Вроде разобрался, действительно, сначала нужно удалить конкретное значение параметра из договора, потом задать новое, примерно вот так:
Код:
cpm.deleteParamForContract( "contract_parameter_type_3", cid );
cpm.setEmailParam( cid, pid, emailParam, false, 1 );



Для обновления email достаточно вызвать:
Код:
cpm.setEmailParam( cid, pid, emailParam, false, 1 );


Если у вас в договоре более одного параметра типа email, код
Код:
cpm.deleteParamForContract( "contract_parameter_type_3", cid );

удалит все параметры

Автор:  DDPaul [ 28 дек 2009, 13:03 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

При вызове cpm.setEmailParam( cid, pid, emailParam, false, 1 ) MySQL-сервер получает вот такую команду:

Код:
INSERT INTO contract_parameter_type_3 SET cid=12, pid=19, email='test@mail.ru;'


Наверное должен быть UPDATE вместо INSERT?

Версия сервера биллинга 4.6.641.

Автор:  skn [ 28 дек 2009, 18:54 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

там несколько кривой код для того что бы UPDATE вызвался добавьте

Код:
emailParam.setEmailId( 1 );

Автор:  DDPaul [ 28 дек 2009, 19:23 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Да, так работает, спасибо.

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

Пытаюсь сделать так:
Код:
...
ContractParamChangedEvent cpce = new ContractParamChangedEvent( cid, pid, emailParam );


Потом вроде бы нужно запустить EventProcessor и воспользоваться его методом addEvent(), но вот с какими параметрами вызвать конструктор EventProcessor()?

Выдержка из API:
Код:
EventProcessor(DefaultServerSetup setup, boolean processMode, ExtraEventProcessor extraProccessor)


Конкретно ставит в тупик ExtraEventProcessor. Это, насколько я понял, интерфейс, который реализуется классом EventProcessor. Моих знаний в Java и API BGBilling не хватает, чтобы разрешить эту проблему курицы и яйца.

Автор:  dimOn [ 30 дек 2009, 13:00 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Вам это и не нужно разрешать, это просто дополнительный эвентпроцессор, да и не туда смотрите, не нужно на объявление его глядеть)

Код:
EventProcessor.getProcessor().addEvent( cpce );

Автор:  skn [ 30 дек 2009, 15:33 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

я немного не понял где и что не меняется после изменения мыла. можно скриншотик?

Автор:  DDPaul [ 30 дек 2009, 20:00 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Я сделал формочку для action'а как на скриншоте web1.png. Значение для поля Email подставляется следующим образом:

Код:
...
<xsl:variable name="email" select="/data/contract_data/parameters/parameter[@pid='19']/@value"/>
...
<tr>
   <th>Email:</th>
   <td><input type="text" name="email" value="{$email}" size="30" maxlength="30"/></td>
</tr>
...


В конфигурации биллинга, естественно, установлена опция web.add.contract=1.

В клиенте биллинга, соответственно, отображается то же значение.

Скриншот после изменения email'а - web2.png. Видно, что значение в переменной $email осталось то же самое.

Кусок кода action'а:

Код:
...
String email = request.getParameter( "email" );
if( email != null )
{
   pid = 19;
   
   // Get old value
   ContractEmailParamValue emailParam = cpm.getEmailParam( cid, pid );
   String oldEmail = emailParam.getEmail();

   if( !email.equals( oldEmail ))
   {
      // Set new value and throw event
      emailParam.setEmail( email );
      emailParam.setEmailId( 1 );
      cpm.setEmailParam( cid, pid, emailParam, false, 1 );
      event = new ContractParamChangedEvent( cid, pid, emailParam );
      EventProcessor.getProcessor().addEvent( event );
   }
}
...


В server.log event появляется:
Код:
12-30/16:28:57  INFO [http-8080-1] EventProcessor - Add event to queue Event bitel.billing.server.script.bean.event.ContractParamChangedEvent cid: 43; module: 0; type: 9


В клиенте биллинга отображается новое значение параметра (bg2.png).

Однако генерируемый биллингом XML для личного кабинета не меняется:
Код:
<parameters>
    ...
    <parameter pid="19" pt="3" sort="25" title="E-mail" value="test@mail.ru; "/>
    ...
</parameters>


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

Кроме того, если несколько раз менять параметр через клиент биллинга, то возникает такая же проблема - в личном кабинете, в конце концов, "устаканивается" какое-нибудь значение и не меняется вплоть до перезапуска.

Автор:  supp [ 30 дек 2009, 20:24 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

отличная затея. после отладки ждем подробное описание.

Автор:  skn [ 30 дек 2009, 21:00 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

добавьте в код акшена

Код:
request.getSession().removeAttribute( "contract_data" );

Автор:  DDPaul [ 13 янв 2010, 20:15 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Добрый день, с прошедшими праздниками :) Спасибо за советы, обновление параметра работает.

Теперь хочется прикрутить еще и валидацию параметра с помощью обработи события "Перед изменением параметра договора", как в Wiki.

Для тестирования повесил на обработку вот такой скрипт поведения:
Код:
import bitel.billing.server.contract.bean.*;

pid = event.getParamId();
value = event.getValue();
 
// Проверка значения параметра типа Email
if( value instanceof ContractEmailParamValue )
{
    value = value.getEmail();
    print( "pid=" + pid + "; value=" + value );
   
    if( value.length() > 10 )
    {
        event.setError( "Длина параметра больше 10" );
        return;
    }
}

Скрипт работает, при попытке ввести email длиннее 10 символов, клиент биллинга выдает предупреждение об ошибке.

Из action'а это событие вызываю с помощью класса ContractParamBeforeChangeEvent. Вот кусок кода:
Код:
// Set email parameter
ContractEmailParamValue emailParam = cpm.getEmailParam( cid, pid );
String paramValue = request.getParameter( "email" );
emailParam.setEmail( paramValue );
emailParam.setEmailId( 1 );
cpm.setEmailParam( cid, pid, emailParam, false, 1 );

// Throw "before change" event for validation
ContractParamBeforeChangeEvent eventBefore = new ContractParamBeforeChangeEvent( cid, pid, emailParam );
if( eventBefore != null )
{
    EventProcessor.getProcessor().addEvent( eventBefore );
    errorBefore = eventBefore.getError();

    // If validation passes then throw "parameter changed" event
    if( errorBefore == null )
    {
   event = new ContractParamChangedEvent( cid, pid, emailParam );
   EventProcessor.getProcessor().addEvent( event )
    }
}


Т.е. если обработчик события ContractParamBeforeChangeEvent не выдал ошибку, то сгенерировать событие ContractParamChangedEvent.

В итоге, при изменении параметра через Web-интерфейс, скрипт поведения по событию "Перед изменением параметра договора" запускается (лог без ошибок, значения pid и value выводятся), но возвращаемое методом getError() значение всегда равно null, независимо от длины email'а.

Что можете посоветовать?

Автор:  Amir [ 14 янв 2010, 14:27 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Вызывайте не addEvent, а processEvent

Автор:  supp [ 14 янв 2010, 15:57 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

ждем подробного описания

Автор:  DDPaul [ 25 янв 2010, 16:22 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Скоро выложу :) Пока еще один вопрос возник - можно ли класс или хотя бы функцию, описанные в "Библиотеке скриптов" вызывать из action'а? Т.е. хочется что-то типа директивы includeBGBS для скриптов поведения.

Вроде понимаю, что включить "Библиотеку скриптов" можно таким образом
Код:
import ru.bitel.bgbilling.kernel.script.common.bean.ScriptLibrary.*;

А как оттуда вытащить функции?

Автор:  DDPaul [ 28 янв 2010, 13:53 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Распишу свой вопрос чуть подробнее.

Для связки переменной из POST-запроса и кодом параметра в биллинге я использую HashMap и определяю дополнительный класс:

Код:
public class AdditionalParams {
    public static HashMap<String,Integer> pids()
    {
   HashMap<String,Integer> hash = new HashMap<String,Integer>();
   hash.put( "email",   19 );
   hash.put( "login",   33 );
   return hash;
    }
    ...
}


В action'е, соответственно:

Код:
import bitel.billing.server.contract.AdditionalParams;
HashMap<String,Integer> pids = AdditionalParams.pids()
String  paramKey = "email";
String  paramValue = request.getParameter( paramKey );
Integer paramID = pids.get( paramKey );


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

Так вот мне не очень нравится то, что при добавлении нового параметра (который можно изменять из личного кабинета) нужно изменять класс AdditionalParams, перекомпилировать его, и, как следствие, перезапускать биллинг.

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

Автор:  DDPaul [ 03 фев 2010, 16:32 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Уважаемые разработчики, вопрос все еще актуален.

Автор:  Amir [ 03 фев 2010, 18:00 ]
Заголовок сообщения:  Re: Свой action в личном кабинете

Такие параметры мы обычно храним в конфиге сервера, а получаем
Код:
setup.get( key, def )
setup.getInt( key, def )

Главное чтобы имя вашего параметра не пересеклось вдруг с нашим.

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