Как сделать разные карточки для разных типов заказов

Задача

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

Описание решения

  1. Создаём обработчик, который при добавлении нового заказа будет предлагать в отдельном окне выбрать тип создаваемого заказа.
  2. Создаём обработчик, который будет перед открытием карточки заказа определять тип заказа и открывать карточку, соответствующую этому типу заказа.
  3. Настраиваем выбор типа проекта по умолчанию в карточке проекта.
  4. Создаём копии каталога ./config/sections/Project и настраиваем в каждой копии свой вид карточки.

Далее представлено решение с примерами кода.

Обработчик выбора типа заказа при создании заказа

В файле /config/sections/Project/g_project.js прописываем обработчик project_addNewProject(), который будет вызываться при создании нового заказа.

// При добавлении нового заказа показать форму выбора типа заказа
function project_addNewProject(p_grid_id, p_mode) {
    if (p_mode == 0) {
        new Ajax.Request(g_path+g_Project_ScriptFileName, {
            parameters:  {
                '_func': 'Project_GetTypes'
            }, 
            //После получения списка возможных типов проектов, отобразим их
            onSuccess: function(transport) {
                var l_res = transport.responseText.evalJSON();
 
                //Доступные типы заказов
                var select_sql = '<select id="NewProjectTypeSelect" ' +
                    'class="edtText" onblur="this.className = \'edtText\';" ' +
                    'onfocus="this.className = \'edtText_selected\';" ' +
                    'style="width: 250px;">';
                select_sql = select_sql + '<option value="" selected="selected"></option>';
                for (var i=0; i<l_res.length; i++) {
                    select_sql = select_sql + '<option value="'+l_res[i].Code+'">'+l_res[i].Name+'</option>';
                }
                select_sql = select_sql + '</select>';
 
                //Отобразим форму выбора типа заказа
                Dialog.confirm('Укажите тип создаваемого заказа:<br>' + select_sql, {
                    onOk: function() { project_addNewProject(p_grid_id, 1); }, 
                    className: "iris_win", 
                    width: 300, 
                    height: null, 
                    buttonClass: "button", 
                    okLabel: "ОК", 
                    cancelLabel: "Отмена"
                });
                return;
            }
        });
    }
 
    var select = $('NewProjectTypeSelect').up().down('select');
    var value = select.options[select.selectedIndex].value;
    if (value == '') {
        select.className = 'edtText_empty';
        return;
    }
    Dialog.closeInfo();
 
    //Откроем карточку нового заказа выбранного типа
    openCard({
        source_type: 'grid',
        source_name: 'Project',
        rec_id: '',
        parent_id: p_grid_id,
        card_params:
            '{"mode": "'+value+'", ' +
            '"detail": "'+$(p_grid_id).getAttribute('detail_name')+'", ' +
            '"parent_rec_id": "'+$(p_grid_id).getAttribute('detail_parent_record_id')+'"}'
    });
}

В конец функции project_grid_init() пропишем вызов этого обработчика.

var elem = getGridFooterTable(p_grid_id);
elem.down('input[value="Добавить"]').hide().insert({
    after: '<input ' +
        'class="button" ' +
        'type="button" ' +
        'title="Добавить новую запись" ' +
        'value="Добавить" ' +
        'onclick="project_addNewProject(\''+p_grid_id+'\', 0)" ' +
        'style="width: 70px;"/>'
});

В результате при добавлении нового заказа будет предварительно отображаться окно с выбором типа заказа.

Укажите тип создаваемого заказа. Газ физлицо.

Обработчик при открытии карточки заказа

Создаём файл ./config/sections/Project/s_project.php, в котором прописываем обработчик при открытии существующего заказа.

<?php
 
//********************************************************************
// Серверная логика карточки заказа
//********************************************************************
include_once GetPath().'/config/common/Lib/lib.php';
 
 
//По коду типа заказа возвращает имя секции заказа
function GetProjectSection($project_type) {
    return 'Project'.($project_type ? '-' : '').$project_type;
}
 
 
//Перед открытием карточки в завистмости от типа проекта подставим нужную карточку
function Project_onPrepare($params) {
if ($params['card_params'] == 'undefined')
    $params['card_params'] = null;
 
    $card_params = json_decode($params['card_params'], true);
    if ($card_params != null) {
        // если передан параметр, указывающий какую карточку открыть, то откроем нужную карточку
        if ($card_params['mode'] != null) {
            $params['parent_type'] = 'grid';
            $params['source_name'] = GetProjectSection($card_params['mode']);
            $params['parent_page'] = $card_params['mode'].'$params-delimenter$'.'{"detail": "'.$card_params['detail'].'", "parent_rec_id": "'.$card_params['parent_rec_id'].'"}';
            $params['detail_name'] = '';
            $params['detail_column_value'] = '';     
            //$params['card_params'] = '{"detail": "'+$card_params['detail']+'"}'; - card_params передаются через parent_page
            return $params;
        }
        // 
        if ($card_params['detail'] != null) {
            // если карточка открыта из вкладки, то заполним ее поля компания и контакт
            if ($card_params['detail'] == 'd_Contact_Project') {
                $contact_name = GetFieldValueByFieldValue('contact', 'id', $card_params['parent_rec_id'], 'name');
                $values = FieldValueFormat('ContactID', $card_params['parent_rec_id'], $contact_name, $values);
 
                $account_id = GetFieldValueByFieldValue('contact', 'id', $card_params['parent_rec_id'], 'accountid');
            }
            if ($card_params['detail'] == 'd_Account_Project') {
                $account_id = $card_params['parent_rec_id'];
            }
            if ($account_id != '') {
                $account_name = GetFieldValueByFieldValue('account', 'id', $account_id, 'name');
                $values = FieldValueFormat('AccountID', $account_id, $account_name, $values);
            }
            return $values;
        }
    }
 
    // если режим update, то покажем нужную карточку в зависимости от кода типа заказа
    if ($params['mode'] == 'update') {
        $con = db_connect();
        $cmd = $con->prepare("select T1.code as pt_code ".
            "from iris_project T0 left join iris_projecttype T1 on T0.projecttypeid = T1.id ".
            "where T0.id=:id");
        $cmd->execute(array(":id" => $params['rec_id']));
        $record = current($cmd->fetchAll(PDO::FETCH_ASSOC));
        $params['parent_type'] = 'grid';
        $params['source_name'] = GetProjectSection($record['pt_code']);
        $params['parent_page'] = $record['pt_code'];
 
        $params['parent_type'] = 'grid';
        $params['detail_name'] = '';
        $params['detail_column_value'] = '';
    }
 
    return $params;
}

Прописываем вызов этого обработчика в structure.xml в теге EDITCARD.

php_source_file="config/sections/Project/s_project.php"
php_on_prepare="Project_onPrepare"

Выбор типа проекта по умолчанию

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

В файле c_project.php комментируем следующую строку в функции Project_GetDefaultValues().

// Значения справочников
$l_result = GetDictionaryValues(
    [
        ['Dict' => 'ProjectState', 'Code' => 'Plan'],
        ['Dict' => 'ProjectStage', 'Code' => 'Sale_Info'],
        ['Dict' => 'Currency', 'Code' => 'RUB'],
    ], 
    $con
);

В файле c_project.js комментируем следующую строку в функции c_Project_GetDefaultValues_end().

try {
    //p_form.ProjectTypeID.removeAttribute('disabled');
} 
catch (e) {};

В этот же файл добавляем функцию получения кода типа проекта.

//Получить код типа проекта по названию раздела
function c_project_getProjectType(p_form) 
{
    var projectSection = p_form._source_name.value;
    var projectTypeCode = 'GasPhysic'; //Тип по умолчанию
    if (projectSection != 'Project') {
        projectTypeCode = projectSection.split('-')[1];
    }
    return projectTypeCode;
}

Также в этом же файле меняем строку

c_Common_SetDefaultValues(l_form, c_Project_ScriptFileName, 
    function() { c_Project_GetDefaultValues_end(l_form); });

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

var projectTypeCode = c_project_getProjectType(l_form);
try {
    SetSelectValueByAttribute(l_form.ProjectTypeID, 'code', projectTypeCode);
}
catch (e) {};
 
c_Common_SetDefaultValues(l_form, c_Project_ScriptFileName, 
    function() { c_Project_GetDefaultValues_end(l_form); }, 
    [{'Name': 'sectioncode', 'Value': projectTypeCode}]);

Также в файле structure.xml необходимо добавить атрибут db_field_ext для поля ProjectTypeID.

<FIELD elem_type="select" caption="Тип"
    db_field="ProjectTypeID" db_field_ext="code" mandatory="no" datatype="id"
    row_type="fk_column" row_type_parent_table="iris_ProjectType"
    row_type_parent_display_column="Name" />

Создание копий каталога раздела

Создайте копии каталога ./config/sections/Project. Назовите их так: Project-<Код типа заказа>. Удалите из копий каталога все файлы кроме structure.xml.

В примере, на основе которого подготовлен данный материал, коды типов заказа были такие: Electric, GasLegal, GasLimit, GasPhysic, Ground. Поэтому структура каталогов в нашем случае такова.

Project
  c_project.js
  c_project.php
  dc_advantage.js
  dc_product.js
  dc_product.php
  g_project.js
  g_project.php
  s_project.php
  structure.xml

Project-Electric
  structure.xml

Project-GasLegal
  structure.xml

Project-GasLimit
  structure.xml

Project-GasPhysic
  structure.xml

Project-Ground
  structure.xml

Сделайте в файлах structure.xml изменения, чтобы в карточке каждого типа заказа отображались нужные поля.