Изменение параметров договора из личного кабинета

Материал из BiTel WiKi

Версия от 10:53, 16 февраля 2010; DDPaul (Обсуждение | вклад)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Определение нужных параметров.

Сначала нужно создать параметры - в справочнике «Параметры договоров». Для обращения к ним из скриптов и action'а достаточно знать код параметра (pid). Однако, для удобства, решено было использовать мнемонические обозначения параметров, попросту говоря, имена.

Связь (map) между кодом параметра и именем задается в конфигурации биллинга. Нам будут нужны следующие map'ы (в скобках - префикс):

  • по имени параметра, полученного из объекта request (т.е. из POST-запроса) определить его код (pid);
  • по имени параметра определить его описание, которое будет отображаться в личном кабинете (desc);
  • по коду параметра определить его имя - для обработки событий и отсылки сообщения (name).

Для того, чтобы имена наших переменных не пересекались с другими (стандартными) параметрами конфигурации BGBilling, разумно использовать префикс, например, название компании.

# Имя параметра -> ID параметра
my.pid.email=19
my.pid.login=33
#
# Имя параметра -> Описание параметра
my.desc.email=Email
my.desc.login=Логин
#
# ID параметра -> Имя параметра
my.name.19=email
my.name.33=login


Обработка событий в BGBilling.

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

  1. Создать новый скрипт поведения "Параметры".
  2. Создать обработчик для события "Перед изменением параметра договора" (как в Валидация текстового параметра)
import ru.bitel.bgbilling.server.util.Setup;
import bitel.billing.server.contract.bean.*;
import java.util.*;
 
// Соответствие ID параметра договора и ключевого слова, обозначающего этот параметр
paramNames = Setup.getSetup().getHashValuesWithPrefix( "my.name." );
 
cid = event.getContractID();
pid = event.getParamId();
paramValue = event.getValue();
paramName = paramNames.get( String.valueOf( pid ));
//print( "cid: " + cid + ", pid: " + pid + ", paramValue: " + paramValue + ", paramName: " + paramName );
 
if( paramName != null )
{
    // Проверка значения параметра типа Email
    if( paramName.equals( "email" ))
    {
        // Email - http://regexlib.com/REDetails.aspx?regexp_id=21
        // Выражение расширено для проверки списка адресов, разделенных ";" и опциональными пробелами
        REGEX = "^([\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}(\\n|;\\s*|))+$";
 
        paramValue = paramValue.getEmail();
 
        if( !paramValue.matches( REGEX )) {
            event.setError( "Неверный формат Email" );
        return;
    }
    }
 
    // Проверка значения для телефонного номера
    if( paramName.equals( "vfaxnumber" ))
    {
        // Телефонный номер - (495) 44-2221-1
        REGEX1 = "^\\(\\d+\\)\\s*[\\d\\-]+$";
        // Телефонный номер - 8-903-44-2221-1 или 890311
        REGEX2 = "^\\d[\\d\\-]+$";
        // Телефонный номер - +79034422211
        REGEX3 = "^\\+\\d+$";
 
        if( !paramValue.matches(REGEX1) && !paramValue.matches(REGEX2) && !paramValue.matches(REGEX3) ) {
        event.setError( "Неверный формат телефонного номера" );
        return;
        }
    }
}

3. Создать обработчик для события "Измененен параметр договора".

import ru.bitel.bgbilling.server.util.Setup;
import bitel.billing.server.contract.bean.*;
import bitel.billing.server.util.MailMsg;
 
// Получатель email'а
emailAddr = "my@email.com";
 
// Соответствие ID параметра договора и ключевого слова, обозначающего этот параметр
paramNames = Setup.getSetup().getHashValuesWithPrefix( "my.name." );
 
cid = event.getContractID();
pid = event.getParamId();
paramValue = event.getValue();
paramName = paramNames.get( String.valueOf( pid ));
//print( "cid: " + cid + ", pid: " + pid + ", paramValue: " + paramValue + ", paramName: " + paramName );
 
// Если измененный параметр есть в массиве paramNames, то провести процедуру коррекции и отправить письмо
if( paramName != null )
{
    // Обработка значение параметра типа Email
    // При изменении через клиент BGBilling'а адреса разделяются "\n"
    if( paramName.equals( "email" )) {
        paramValue = paramValue.getEmail();
        paramValue = paramValue.replaceAll( "\n", "; ");
    }
 
    // Отправка письма, текст сообщения - "параметр:значение"
    if( paramValue != null ) {
        txt = paramName + ":" + paramValue + "\n";
        cpm = new ContractParameterManager( con );
        recp = emailAddr;
        new MailMsg( setup ).sendMessage( recp, "Parameters changed", txt );
    }
}


Action.

Алгоритм работы action'а:

  1. Определить ID клиента (см. Получение текущего пользователя биллинга).
  2. Просканировать список всех параметров, и, если, было задано новое значение (через POST-запрос), то:
  3. Сгенерировать событие ContractParamBeforeChangeEvent - для валидации параметра.
  4. Если параметр прошел валидацию, то установить новое значение и сгенеририровать событие ContractParamChangedEvent (для выполнения нужных действий с новым значением параметра)
  5. По результатам выполнения заполнить XML-отчет, который пригодится для отображения результатов в ЛК.
package bitel.billing.server.contract;
 
import java.sql.SQLException;
import java.util.List;
import java.util.HashMap;
import java.util.Iterator;
import java.security.AccessController;
import javax.security.auth.Subject;
import org.w3c.dom.Element;
import bitel.billing.server.admin.bean.User;
import bitel.billing.server.admin.bgsecure.bean.UserLoginModule.UserPrincipal;
import bitel.billing.server.contract.bean.*;
import bitel.billing.server.script.bean.event.*;
import bitel.billing.server.contract.action.ActionBase;
import ru.bitel.bgbilling.server.util.Setup;
 
public class WebAction_AdditionalParams extends ActionBase
{
    @Override
    public void doAction()
            throws SQLException
    {
    // Object request holds all information about HTTP-request
    request.getSession();
 
    // Get customer ID
    Subject subject = Subject.getSubject( AccessController.getContext() );
    if( subject != null )
    {
        for( UserPrincipal userPrincipal : subject.getPrincipals( UserPrincipal.class ) )
        {
        User currentUser = userPrincipal.getUser();
        Integer cid = currentUser.getID();
        }
    }
 
    if( cid != 0 )
    {
        Setup setup = Setup.getSetup();
        ContractParameterManager cpm = new ContractParameterManager( con );
        Integer pid = 0;
        Integer reportIsNeeded = 0;
        Element report = createElement( rootNode, "report" );
        Element element;
 
        // Get parameter IDs and descriptions from BGBilling configuration
        HashMap<String,String> pids = (HashMap<String,String>) setup.getHashValuesWithPrefix( "my.pid." );
        HashMap<String,String> descriptions = (HashMap<String,String>) setup.getHashValuesWithPrefix( "my.desc." );
 
        // Cycle through parameters set
        Iterator iterator = pids.keySet().iterator();
        while( iterator. hasNext() )
        {
        String paramName = String.valueOf( iterator.next() );
        String paramDesc = descriptions.get( paramName );
        String paramValue = request.getParameter( paramName );
        String oldParamValue;
        String errorBefore = "";
        ContractEmailParamValue emailParam = null;
        ContractParamBeforeChangeEvent eventBefore = null;
        ContractParamChangedEvent event = null;
 
        // If value from POST-request exists
        if( paramValue != null )
        {
            pid = Integer.parseInt( pids.get( paramName ));
 
            // Get old value (email parameter needs special handling)
            if( paramName.equals( "email" )) {
            emailParam = cpm.getEmailParam( cid, pid );
            oldParamValue = emailParam.getEmail();
            } else {
            oldParamValue = cpm.getStringParam( cid, pid );
            }
 
            // If value has been changed (from LK) then ...
            if( !paramValue.equals( oldParamValue ))
            {
            // Prepare new value to parameter and set "before change" event (email parameter needs special handling)
            if( paramName.equals( "email" )) {
                emailParam.setEmail( paramValue );
                emailParam.setEmailId( 1 );
                eventBefore = new ContractParamBeforeChangeEvent( cid, pid, emailParam );
            } else {
                eventBefore = new ContractParamBeforeChangeEvent( cid, pid, paramValue );
            }
 
            if( eventBefore != null )
            {
                // Create "row" element for XML report
                element = createElement( report, "row" );
                element.setAttribute( "parameter", paramDesc );
 
                // Throw "before change" event to handler (BGBilling server) and get error message
                EventProcessor.getProcessor().processEvent( eventBefore );
                errorBefore = eventBefore.getError();
 
                if( errorBefore == null )
                {
                // If handler returns "ok" then set new parameter value and set "parameter changed" event
                if( paramName.equals( "email" )) {
                    cpm.setEmailParam( cid, pid, emailParam, false, 1 );
                    event = new ContractParamChangedEvent( cid, pid, emailParam );
                } else {
                    cpm.setStringParam( cid, pid, paramValue, 1 );
                    event = new ContractParamChangedEvent( cid, pid, paramValue );
                }
 
                if( event != null )
                {
                    // Throw "parameter changed" event and set attributes for XML report
                    EventProcessor.getProcessor().addEvent( event );
                    element.setAttribute( "status", "ok" );
                    element.setAttribute( "value", String.valueOf( paramValue ));
                    reportIsNeeded = 1;
                }
                } else {
                // If handler returns error then set attributes for XML report only
                element.setAttribute( "status", "error" );
                element.setAttribute( "value", String.valueOf( errorBefore ));
                reportIsNeeded = 1;
                }
            }
            }
        }
        }
 
        // Renew XML element with contract parameters and set status variable for Web
        if( reportIsNeeded == 1 )
        {
            request.getSession().removeAttribute( "contract_data" );
            rootNode.setAttribute("status","ok");
        }
    }
    }
}


Шаблон личного кабинета.

Внести необходимые изменения в шаблон ЛК, а именно, common.xsl:

...
<!-- Дополнительные параметры договора -->
<xsl:variable name="email" select="/data/contract_data/parameters/parameter[@pid='19']/@value"/>
<xsl:variable name="login" select="/data/contract_data/parameters/parameter[@pid='33']/@value"/>
 
<!-- Шаблон меню -->
<xsl:template name="standart_menu">
<tr>
    <th><img src="img/strelki.gif"/></th>
    <td><a href="?">Новости</a></td>
</tr>
<tr>
    <th><img src="img/strelki.gif"/></th>
    <td><a href="?action=AdditionalParams&amp;mid=contract">Доп. параметры</a></td>
</tr>
...

и main.xsl:

...
<xsl:template name="title">
<xsl:choose>
...
    <xsl:when test="data/@action = 'AdditionalParams'">Дополнительные параметры</xsl:when>
...
    <xsl:otherwise>НОВОСТИ</xsl:otherwise>
</xsl:choose>
</xsl:template>
 
<xsl:template match="/data">
<xsl:choose>
...
    <xsl:when test="@action = 'AdditionalParams'">
        <xsl:call-template name="AdditionalParams"/>
    </xsl:when>
...
</xsl:choose>
</xsl:template>
 
<!-- Дополнительные параметры -->
<xsl:template name="AdditionalParams">
 
    <form method='post' action='{$WEBEXECUTER}'>
    <xsl:call-template name="action"/>
    <xsl:call-template name="error"/>
    <input type="hidden" name="command" value="change"/>
    <xsl:if test="@status = 'ok'">
        <div class="infoMessage">
        <xsl:for-each select="/data/report/row">
            <xsl:if test="@status = 'ok'">
            <xsl:value-of select="@parameter" /> изменен на <xsl:value-of select="@value" /><br />
            </xsl:if>
            <xsl:if test="@status = 'error'">
            При изменении "<xsl:value-of select="@parameter" />" произошла ошибка: <xsl:value-of select="@value" /><br />
            </xsl:if>
        </xsl:for-each>
        </div>
    </xsl:if>
 
    <div class="report">
          <table cellspacing='1' id="idTableChangePassword">
          <col class="col1"/>
          <col class="col2"/>
          <tbody>
            <tr>
              <th>Email:</th>
              <td><input type="text" name="email" value="{$email}" size="30" maxlength="100"/></td>
            </tr>
            <tr>
              <th>Логин:</th>
              <td><input type="text" name="login" value="{$login}" size="30" maxlength="20"/></td>
            </tr>
          </tbody>
          <tfoot>
            <tr><td colspan='2'>
              <xsl:call-template name="submit">
                  <xsl:with-param name="title" select="'Сохранить'"/>
              </xsl:call-template>
            </td></tr>
          </tfoot>
          </table>
    </div>
    </form>
</xsl:template>
Личные инструменты