Дерево страниц

Сравнение версий

Ключ

  • Эта строка добавлена.
  • Эта строка удалена.
  • Изменено форматирование.
Информация
iconfalse
titleПостановка задачи

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

Подсказка
iconfalse

Инструмент:  Палитра XML

Свойства страницы
Статус

Статус
colourGreen
title

ЧЕРНОВИК

ГОТОВО

Раздел
Автор
Действия
Комментарий

панель
На этой странице:
titleРеализация

Оглавление

Постановка задачи
панель
Инструмент
title

Реализация

Примечание

Если есть какие-то нюансы по реализации, указать. Если нет, то удалить данный пункт

<Сопроводительная информация>



Создать схему диалога

importClass(Packages.ru.intertrust.cmj.af.core.AFSession); importClass(Packages.ru.intertrust.cmj.af.exceptions.AFDaoBadParameterException); importClass(Packages.ru.intertrust.cmj.rest.tunable.object.TunableObjectREST); importClass(Packages.ru.intertrust.cmj.rest.tunable.object.TunableObjectREST.Resource); importClass(Packages.ru.intertrust.cmj.rest.tunable.object.action.TunableOperation); importClass(Packages.ru.intertrust.cmj.tunable.object.AnyTunableObject); importClass(Packages.ru.intertrust.cmj.tunable.object.TunableObjectApplication); importClass(Packages.ru.intertrust.cmj.tunable.object.TunableObjectApplication.ClientContextKey); importClass(Packages.ru.intertrust.cmj.tunable.object.common.TunableObjectHelper); importClass(Packages.ru.intertrust.cmj.rest.tunable.object.action.OperationJScriptREST); importClass(Packages.ru.intertrust.cmj.rest.tunable.object.action.OperationJScriptREST.ReturnParamsResource); importClass(Packages.ru.intertrust.cmj.dp.DPApplication); importClass(Packages.ru.intertrust.cmj.rest.rkk.RkkResource); importClass(Packages.ru.intertrust.cmj.af.utils.BeansUtils); importClass(Packages.ru.intertrust.cmj.wf.impl.WorkflowProcessServiceImpl); importClass(Packages.ru.intertrust.cmj.wf.api.ProcessUserTask); importClass(Packages.ru.intertrust.cmj.wf.api.TaskVariables); importClass(Packages.ru.intertrust.cmj.af.misc.AFDateTime); importPackage(Packages.ru.intertrust.cmj.af.utils); importPackage(Packages.ru.intertrust.cmj.af.tuning.impl); importPackage(Packages.ru.intertrust.cmj.af.tuning); importPackage(Packages.ru.intertrust.cmj.rest.tuning); importPackage(Packages.java.util); importPackage(Packages.java.lang); importClass(Packages.org.apache.commons.lang3.exception.ExceptionUtils); function process(paramsResource, returnResource) { if (paramsResource == null) { throw new IllegalArgumentException("paramsResource must no be null."); } paramPackageId = ""; var systemNames = ['ClientContextRequest','RSHBWFDialogOkCancel','RSHBRequestDialogInfo','dlgError','dlgWarning']; paramSchemaName = paramsResource.tuning().getSchema().getName(); if (systemNames.indexOf(paramSchemaName)==-1) { paramPackageId = TunableObjectHelper.getAFInstanceValue(paramsResource.tuning().getValues().get("counter")); } else { paramPackageId = "contextWithResource"; } if (paramPackageId.equals("context")) { createContextResourceRequest(returnResource); } else if (paramPackageId.equals("contextWithResource")) { process_dlg(paramsResource, returnResource); } else if (paramPackageId.equals("answer")) { process_context(paramsResource, returnResource); } else if (paramPackageId.equals("exit")) { process_refresh(paramsResource, returnResource); } } /** * Обработка первого пакета данных с клиента. * @return возвращение контекста открытого документа */ function createContextResourceRequest(returnResource) { var appTNObject = AFSession.get().getApplication(TunableObjectApplication.class); var afObjectContextRequest = appTNObject.createClientContextRequest(TunableObjectApplication.ClientContextKey.resourceid, TunableObjectApplication.ClientContextKey.resource); TunableObjectHelper.putAFInstanceValue(afObjectContextRequest, "counter", "contextWithResource"); returnResource.setResource(TunableObjectREST.Resource.create(afObjectContextRequest)); } /** * Обновление документа * @param paramsResource * @return ресурс первого диалога сценария */ function process_refresh(paramsResource, returnResource) { var ids = TunableObjectHelper.getAFInstanceValue(paramsResource.tuning().getValues().get("selectIds")); var appdp = AFSession.get().getApplication(DPApplication.class); var obj = appdp.getEntityByUNID(ids.get(0)); var res = RkkResource.valueOf(obj); returnResource.setResource(res); } /** * Вывод диалога * @param paramsResource * @return ресурс первого диалога сценария */ function process_dlg(paramsResource, returnResource) { var appTNObject = AFSession.get().getApplication(TunableObjectApplication.class); var id = TunableObjectHelper.getAFInstanceValue(paramsResource.tuning().getValues().get("$id")); var ids = Utils.newArrayList(); ids.add(id); var appdp = AFSession.get().getApplication(DPApplication.class); var version = paramsResource.getVersion(); if (!isActualObject(id, version)){ process_dlginfo(ids,"<Информация>",returnResource); return returnResource.resource; } var message = appTNObject.composeDialog("RSHBWFDialogOkCancel", null, null, null); TunableObjectHelper.putAFInstanceValue(message.tuning(), "message", "Комментарий:"); TunableObjectHelper.putAFInstanceValue(message.tuning(), "isCommentNotRequired", true); TunableObjectHelper.putAFInstanceValue(message.tuning(), "selectIds", ids); TunableObjectHelper.putAFInstanceValue(message.tuning(), "versionContext", version); TunableObjectHelper.putAFInstanceValue(message, "counter", "answer"); returnResource.setResource(TunableObjectREST.Resource.create(message)); } /** * Проверка документа на актуальность * @id индентификатор объекта * @version текущая версия контекста * @return статус актуальности */ function isActualObject(id, version){ var appdp = AFSession.get().getApplication(DPApplication.class); var versionParts = version.split('$$'); var versionContext = versionParts[0]; var obj = appdp.getEntityByUNID(id); if (obj != null){ var versionObj = obj.getVersionStamp().toString(); } return versionContext == versionObj; } /** * Диалог Cообщение * @ids текущий идентификатор документа * @resultMessage сообщение * @return ресурс */ function process_dlginfo(ids, resultMessage,returnResource){ var appTNObject = AFSession.get().getApplication(TunableObjectApplication.class); var message = appTNObject.composeDialog("RSHBRequestDialogInfo", null, null, null); TunableObjectHelper.putAFInstanceValue(message.tuning(), "selectIds", ids); TunableObjectHelper.putAFInstanceValue(message.tuning(), "message", resultMessage); TunableObjectHelper.putAFInstanceValue(message, "counter", "exit"); returnResource.resource = TunableObjectREST.Resource.create(message); return returnResource.resource; } /** * Диалог Предупреждение * @ids текущий идентификатор документа * @resultMessage сообщение * @return ресурс */ function process_dlgWarning(ids, resultMessage,returnResource){ var appTNObject = AFSession.get().getApplication(TunableObjectApplication.class); var message = appTNObject.composeDialog("RSHBRequestDialogInfo", null, null, null); TunableObjectHelper.putAFInstanceValue(message.tuning(), "selectIds", ids); TunableObjectHelper.putAFInstanceValue(message.tuning(), "message", resultMessage); TunableObjectHelper.putAFInstanceValue(message, "counter", "exit"); returnResource.resource = TunableObjectREST.Resource.create(message); return returnResource.resource; } /** * Диалог Ошибка * @ids текущий идентификатор документа * @resultMessage сообщение * @return ресурс */ function process_dlgError(ids, resultMessage,returnResource){ var appTNObject = AFSession.get().getApplication(TunableObjectApplication.class); var message = appTNObject.composeDialog("RSHBRequestDialogInfo", null, null, null); TunableObjectHelper.putAFInstanceValue(message.tuning(), "selectIds", ids); TunableObjectHelper.putAFInstanceValue(message.tuning(), "message", resultMessage); TunableObjectHelper.putAFInstanceValue(message, "counter", "exit"); returnResource.resource = TunableObjectREST.Resource.create(message); return returnResource.resource; } /** * Обработка данных * @param paramsResource * @return ресурс */ function process_context(paramsResource, returnResource) { var ids = TunableObjectHelper.getAFInstanceValue(paramsResource.tuning().getValues().get("selectIds")); var comment = TunableObjectHelper.getAFInstanceValue(paramsResource.tuning().getValues().get("comment")); var version = TunableObjectHelper.getAFInstanceValue(paramsResource.tuning().getValues().get("versionContext")); var appdp = AFSession.get().getApplication(DPApplication.class); var obj = appdp.getEntityByUNID(ids.get(0)); if (!isActualObject(ids.get(0), version)){ process_dlgWarning(ids,"<Информация Предупреждение>",returnResource); return returnResource.resource; } else { process_dlgError(ids,"<Информация Ошибка>",returnResource); return returnResource.resource; } if (obj.tuning().getValues().containsKey("wf") && obj.tuning().getValues().get("wf") != null) { var wf = obj.tuning().getValues().get("wf"); var task_name = wf.getValues().get("task").getValue(); var wf_status = "-"; if (wf.getValues().containsKey("status") && wf.getValues().get("status") != null ) { wf_status = wf.getValues().get("status").getValue(); } var wf_starttime = new AFDateTime(Calendar.getInstance()); if (wf.getValues().containsKey("actiontime") && wf.getValues().get("actiontime") != null ) { wf_starttime = wf.getValues().get("actiontime").getValue(); } else if (wf.getValues().containsKey("starttime") && wf.getValues().get("starttime") != null ){ wf_starttime = wf.getValues().get("starttime").getValue(); } // Получаем задачу var taskId = wf.getValues().get("task_id").getValue(); var workflowProcessService = BeansUtils.getBean("workflowProcessServiceImpl"); var task = workflowProcessService.getTaskById(taskId); // Должна быть только одна задача, завершаем ее, установив переменную if (task != null){ //Запускаем WF task.getTaskVariables().put(task_name + "Result", true); var ProcessActionResult = workflowProcessService.completeUserTask(task); if (ProcessActionResult.hasError()) { rollbackWF(appdp, ids.get(0), obj); var exception = ProcessActionResult.getException(); var stacktrace = ExceptionUtils.getStackTrace(exception); throw new RuntimeException("Не удалось продолжить процесс. Обратитесь к администратору. Ошибка: " + stacktrace); } obj = appdp.getEntityByUNID(ids.get(0)); //запись в Жизненный цикл var currentUser = AFSession.get().currentUser().getBeard(); var executors = wf.getValues().get("assignee").getValues(); var executor = executors.get(0).getValue(); if (task_name.equals("ownerISNegotiationTask")) { if (obj.tuning().getValues().get("servOwnerISBoss") != null && obj.tuning().getValues().get("servOwnerISBoss").getValue() != null) { executor = obj.tuning().getValues().get("servOwnerISBoss").getValue(); } else { executor = null; } } else if (executor.originalData().getType().toString().equals("SYS_ROLE")){ executor = currentUser; } else { if (executors.size() > 1) { for (var i = 0; i < executors.size(); i++) { if (executors.get(i).getValue() == currentUser) { var executor = currentUser; } } } } var startDate = wf_starttime; var endDate = new AFDateTime(Calendar.getInstance()); var result = "Согласовано"; var information = comment; setLifeCycle(obj, startDate, endDate, wf_status, executor, currentUser, result, information); var time = new AFDateTime(Calendar.getInstance()); TunableObjectHelper.putAFInstanceValue(obj.tuning(), "wf.actiontime",time); var approvalBeard = null; var approvalTime = null; if (task_name.equals("initDepHeadNegotiationTask")) { approvalBeard = "approvalByHeadBeard"; approvalTime = "approvalByHeadTime"; } else if (task_name.equals("ownerISNegotiationTask")) { approvalBeard = "approvalByOwnerBeard"; approvalTime = "approvalByOwnerTime"; } if (approvalBeard != null && approvalTime != null) { var propertyBeard = obj.tuning().getSchema().getProperty(approvalBeard); var beardValue = TuningHelper.createPropertyValue(AFSession.get().currentUser().getBeard(), propertyBeard); obj.tuning().getValues().put(approvalBeard, beardValue); var propertyTime = obj.tuning().getSchema().getProperty(approvalTime); var beardTime = TuningHelper.createPropertyValue(new AFDateTime(), propertyTime); obj.tuning().getValues().put(approvalTime, beardTime); } try { obj.save(); } catch (e) { process_dlgError(ids,"<Информация об ошибке>",returnResource); return returnResource.resource; } obj = appdp.getEntityByUNID(ids.get(0)); var res = RkkResource.valueOf(obj); returnResource.setResource(res); } else { throw new RuntimeException("Не найдена задача. Обратитесь к администратору. Идентификатор: " + taskId); } } else { throw new RuntimeException("Не запущен процесс согласования. Обратитесь к администратору. Идентификатор: " + ids.get(0)); } } /** * Откатить статусное состояние WF * @obj объект * id идентификатор объекта * @appdp приложение */ function rollbackWF(appdp, id, obj){ var document = appdp.getEntityByUNID(id); var wf = obj.tuning().getValues().get("wf"); var assignee = null; var task = ""; var status = wf.getValues().get("status").getValue(); var stage = ""; var duration = null; var starttime = null; var finishtime = null; if (wf.getValues().get("assignee") != null) { assignee = wf.getValues().get("assignee").getValues(); task = wf.getValues().get("task").getValue(); stage = wf.getValues().get("stage").getValue(); duration = wf.getValues().get("duration").getValue(); starttime = wf.getValues().get("starttime").getValue(); if (wf.getValues().get("finishtime") != null) { finishtime = wf.getValues().get("finishtime").getValue(); } } TunableObjectHelper.putAFInstanceValue(document.tuning(), "wf.assignee", assignee); TunableObjectHelper.putAFInstanceValue(document.tuning(), "wf.task", task); TunableObjectHelper.putAFInstanceValue(document.tuning(), "wf.status", status); TunableObjectHelper.putAFInstanceValue(document.tuning(), "wf.stage", stage); TunableObjectHelper.putAFInstanceValue(document.tuning(), "wf.duration", duration); TunableObjectHelper.putAFInstanceValue(document.tuning(), "wf.starttime", starttime); TunableObjectHelper.putAFInstanceValue(document.tuning(), "wf.finishtime", finishtime); document.save(); } /** * Запись в Жизненный цикл * @obj объект * @startDate дата начала действия * @endDate дата окончания действия * @action действие * @assignee исполнитель * @currentUser пользователь, выполнивший действие * @result Результат * @information Доп. информация */ function setLifeCycle(obj, startDate, endDate, action, assignee, currentUser, result, information) { var propertyLifecycle = obj.tuning().getSchema().getProperty("wf_lifecycle"); var lifecycle = null; if (obj.tuning().getValues().containsKey("wf_lifecycle") && obj.tuning().getValues().get("wf_lifecycle") != null) { lifecycle = obj.tuning().getValues().get("wf_lifecycle").getValues(); } else { lifecycle = Utils.newArrayList(); } var propertyStartDate = propertyLifecycle.getSchema().getProperty("lifecycle_start_date"); var propertyDate = propertyLifecycle.getSchema().getProperty("lifecycle_date"); var propertyAction = propertyLifecycle.getSchema().getProperty("lifecycle_action"); var propertyAssignee = propertyLifecycle.getSchema().getProperty("lifecycle_assignee"); var propertyCurrentUser = propertyLifecycle.getSchema().getProperty("lifecycle_current_user"); var propertyResult = propertyLifecycle.getSchema().getProperty("lifecycle_result"); var propertyInformation = propertyLifecycle.getSchema().getProperty("lifecycle_information"); var startDateValue = TuningHelper.createPropertyValue(startDate, propertyStartDate); var endDateValue = TuningHelper.createPropertyValue(endDate, propertyDate); var actionValue = TuningHelper.createPropertyValue(action, propertyAction); var currentUserValue = TuningHelper.createPropertyValue(currentUser, propertyCurrentUser); var assigneeValue = TuningHelper.createPropertyValue(assignee, propertyAssignee); var resultValue = TuningHelper.createPropertyValue(result, propertyResult); var informationValue = TuningHelper.createPropertyValue(information, propertyInformation); var wf_lifecycle = new AFInstanceObjectImpl(propertyLifecycle.getSchema()); wf_lifecycle.getValues().put("lifecycle_start_date", startDateValue); wf_lifecycle.getValues().put("lifecycle_date", endDateValue); wf_lifecycle.getValues().put("lifecycle_action", actionValue); wf_lifecycle.getValues().put("lifecycle_assignee", assigneeValue); wf_lifecycle.getValues().put("lifecycle_current_user", currentUserValue); wf_lifecycle.getValues().put("lifecycle_result", resultValue); wf_lifecycle.getValues().put("lifecycle_information", informationValue); lifecycle.add(wf_lifecycle); var lifecycleValue = new AFInstanceArrayImpl(propertyLifecycle.getSchema(), lifecycle); obj.tuning().getValues().put("wf_lifecycle", lifecycleValue); }
Блок кода
languagejs
xml
titleСхема диалога
<?xml version='1.0' encoding='UTF-8'?>
<schemas xmlns="http://www.intertrust.ru/schema/palette/tn-schema">
  <schema extends="Dialog" name="CustomDialog">
    <string name="message" temporal="true">
	 	<meta>
        	<documentation>Заголовок диалога</documentation>
        </meta>
	</string>
    <string name="selectIds" temporal="true" array="true">
		<meta>
        	<documentation>Выбранные идентификаторы объектов</documentation>
        </meta>
	</string>
    <string name="counter" temporal="true">
		<meta>
        	<documentation>Счетчик диалогов</documentation>
        </meta>
	</string >
    <string name="comment" temporal="true">
	 	<meta>
        	<documentation>Комментарий</documentation>
        </meta>
	</string>
    <string name="versionContext" temporal="true">
	 	<meta>
        	<documentation>Текущая версия объекта</documentation>
        </meta>
	</string>
  </schema>
</schemas>


Создать форму диалога

Блок кода
languagexml
titleФорма диалога
<?xml version='1.0' encoding='UTF-8'?>
<ui xmlns="http://www.intertrust.ru/schema/palette/tn-ui">
  <form schema-ref="CustomDialog" id="CustomDialog" projection="default">
    <properties>
      <hide condition-union="AND">
        <negative-condition-ref ref="dialog"/>
      </hide>
    </properties>
    <component>
      <field attribute-ref="message">
        <properties>
          <read-only condition-union="AND">
            <condition>true</condition>
          </read-only>
        </properties>
      </field>
      <field attribute-ref="comment">
        <hint-in-field>${ui.form.CustomDialog.field.Comment.name:Комментарий}</hint-in-field>
        <appearance multiline="true">
          <limit height="4" max-lenght="510"/>
        </appearance>
      </field>
      <button name="${ui.form.CustomDialog.button.Ок:Ок}">
        <action>
          <system name="submit"/>
        </action>
      </button>
      <button name="${ui.form.CustomDialog.button.Cancel:Отмена}">
        <action>
          <system name="cancel"/>
        </action>
      </button>
    </component>
  </form>
</ui>


Создать handler (JS-Обработчик операций)

Блок кода
languagexml
titleОбработчик операций
<?xml version='1.0' encoding='UTF-8'?>
<ui xmlns="http://www.intertrust.ru/schema/palette/tn-ui">
    <handler name="Новая кнопка" id="CustomHandlerName">
        <meta>
            <documentation></documentation>
        </meta>
        <script lang="JavaScript"><![CDATA[код кнопки]]></script>
	</handler>
</ui>
Блок кода
languagejs
titleШаблон кода кнопки
linenumberstrue
collapsetrue
importClass(Packages.ru.intertrust.cmj.af.core.AFSession);
importClass(Packages.ru.intertrust.cmj.af.exceptions.AFDaoBadParameterException);
importClass(Packages.ru.intertrust.cmj.rest.tunable.object.TunableObjectREST);
importClass(Packages.ru.intertrust.cmj.rest.tunable.object.TunableObjectREST.Resource);
importClass(Packages.ru.intertrust.cmj.rest.tunable.object.action.TunableOperation);
importClass(Packages.ru.intertrust.cmj.tunable.object.TunableObjectApplication);
importClass(Packages.ru.intertrust.cmj.tunable.object.TunableObjectApplication.ClientContextKey);
importClass(Packages.ru.intertrust.cmj.tunable.object.common.TunableObjectHelper);
importClass(Packages.ru.intertrust.cmj.rest.tunable.object.action.OperationJScriptREST);
importClass(Packages.ru.intertrust.cmj.rest.tunable.object.action.OperationJScriptREST.ReturnParamsResource);
importClass(Packages.ru.intertrust.cmj.dp.DPApplication);
importClass(Packages.ru.intertrust.cmj.rest.rkk.RkkResource);
importClass(Packages.ru.intertrust.cmj.af.utils.BeansUtils);
importClass(Packages.ru.intertrust.cmj.af.misc.AFDateTime);
importPackage(Packages.ru.intertrust.cmj.af.utils);
importPackage(Packages.ru.intertrust.cmj.af.tuning);
importPackage(Packages.ru.intertrust.cmj.rest.tuning);
importPackage(Packages.java.util);
importPackage(Packages.java.lang);


/**
 * Стартовая функция
 */
function process(paramsResource, returnResource) {

    if (paramsResource == null) {
        throw new IllegalArgumentException("paramsResource must no be null.");
    }
	
	var systemNames = ['ClientContextRequest','CustomDialog','dlgInfo','dlgError','dlgWarning'];
	
	paramSchemaName = paramsResource.tuning().getSchema().getName();
	var paramPackageId = "";
	if (systemNames.indexOf(paramSchemaName)!=-1) {
		paramPackageId = TunableObjectHelper.getAFInstanceValue(paramsResource.tuning().getValues().get("counter"));
	} else {
		paramPackageId = "contextWithResource";
	}

	if (paramPackageId.equals("context")) {
		createContextResourceRequest(returnResource); 	 //Создание открытого контекстного объекта
	} else if (paramPackageId.equals("contextWithResource")) {
		process_dlgCustom(paramsResource, returnResource);	 //Вызов кастомного диалога
	} else if (paramPackageId.equals("answer")) {
		process_context(paramsResource, returnResource); //Основная обработка объекта
	} else if (paramPackageId.equals("exit")) {
		process_refresh(paramsResource, returnResource); //Выход и обновление объекта
	}
}

/**
 * Инициализация контекста открытого документа
 * @return возвращение контекста открытого документа
 */
function createContextResourceRequest(returnResource) {
  var appTNObject = AFSession.get().getApplication(TunableObjectApplication.class);
  var afObjectContextRequest = appTNObject.createClientContextRequest(TunableObjectApplication.ClientContextKey.resourceid, TunableObjectApplication.ClientContextKey.resource);

  TunableObjectHelper.putAFInstanceValue(afObjectContextRequest, "counter", "contextWithResource");
  returnResource.setResource(TunableObjectREST.Resource.create(afObjectContextRequest));
}

/**
 * Обновление документа
 * @param paramsResource
 * @return ресурс первого диалога сценария
 */
function process_refresh(paramsResource, returnResource) {
    var ids = TunableObjectHelper.getAFInstanceValue(paramsResource.tuning().getValues().get("selectIds"));

	var appdp = AFSession.get().getApplication(DPApplication.class);
	var obj = appdp.getEntityByUNID(ids.get(0));

	var res = RkkResource.valueOf(obj);
	returnResource.setResource(res);
}

/**
 * Проверка объекта на актуальность
 * @id идентификатор объекта
 * @version текущая версия контекста
 * @return статус актуальности
 */
 function isActualObject(id, version){
	var versionObj = "";
	
	var appdp = AFSession.get().getApplication(DPApplication.class);
	var obj = appdp.getEntityByUNID(id);
	
	var versionParts = version.split('$$');
	var versionContext = versionParts[0];
	
	if (obj != null){
		versionObj = obj.getVersionStamp().toString(); 
	}
	
	return versionContext == versionObj;
}
 

/**
 * Диалог Информации
 * @ids текущий идентификатор документа
 * @resultMessage сообщение
 * @return ресурс
 */
function process_dlginfo(ids, resultMessage,returnResource){
	var appTNObject = AFSession.get().getApplication(TunableObjectApplication.class);
	var message = appTNObject.composeDialog("dlgInfo", null, null, null);
	TunableObjectHelper.putAFInstanceValue(message.tuning(), "selectIds", ids);
	TunableObjectHelper.putAFInstanceValue(message.tuning(), "message", resultMessage);
	TunableObjectHelper.putAFInstanceValue(message, "counter", "exit");
	returnResource.resource = TunableObjectREST.Resource.create(message);
	return returnResource.resource;
}

/**
 * Диалог Предупреждение
 * @ids текущий идентификатор документа
 * @resultMessage сообщение
 * @return ресурс
 */
function process_dlgWarning(ids, resultMessage,returnResource){
	var appTNObject = AFSession.get().getApplication(TunableObjectApplication.class);
	var message = appTNObject.composeDialog("dlgWarning", null, null, null);
	TunableObjectHelper.putAFInstanceValue(message.tuning(), "selectIds", ids);
	TunableObjectHelper.putAFInstanceValue(message.tuning(), "message", resultMessage);
	TunableObjectHelper.putAFInstanceValue(message, "counter", "exit");
	returnResource.resource = TunableObjectREST.Resource.create(message);
	return returnResource.resource;
}

/**
 * Диалог Ошибка
 * @ids текущий идентификатор документа
 * @resultMessage сообщение
 * @return ресурс
 */
function process_dlgError(ids, resultMessage,returnResource){
	var appTNObject = AFSession.get().getApplication(TunableObjectApplication.class);
	var message = appTNObject.composeDialog("dlgEror", null, null, null);
	TunableObjectHelper.putAFInstanceValue(message.tuning(), "selectIds", ids);
	TunableObjectHelper.putAFInstanceValue(message.tuning(), "message", resultMessage);
	TunableObjectHelper.putAFInstanceValue(message, "counter", "exit");
	returnResource.resource = TunableObjectREST.Resource.create(message);
	return returnResource.resource;
}

/**
 * Вывод настраиваемого диалога
 * @param paramsResource
 * @return ресурс первого диалога сценария
 */
function process_dlgCustom(paramsResource, returnResource) {
    var appTNObject = AFSession.get().getApplication(TunableObjectApplication.class);
	var id = TunableObjectHelper.getAFInstanceValue(paramsResource.tuning().getValues().get("$id")); //id объекта открытого в web
	var ids = Utils.newArrayList(); 
	ids.add(id);
	
	//Проверка на актуальность документа
    var version = paramsResource.getVersion();
	if (!isActualObject(ids.get(0), version)){
		process_dlginfo(ids,"<>",returnResource);
		return returnResource.resource;
	}

	//Кастомный диалог
	var message = appTNObject.composeDialog("CustomDialog", null, null, null);
	TunableObjectHelper.putAFInstanceValue(message.tuning(), "message", "Комментарий:");
	TunableObjectHelper.putAFInstanceValue(message.tuning(), "selectIds", ids);
	TunableObjectHelper.putAFInstanceValue(message.tuning(), "versionContext", version);
	TunableObjectHelper.putAFInstanceValue(message, "counter", "answer");

	returnResource.setResource(TunableObjectREST.Resource.create(message));
}

/**
 * Обработка данных 
 * @param paramsResource
 * @return ресурс
 */
function process_context(paramsResource, returnResource) {
    var ids = TunableObjectHelper.getAFInstanceValue(paramsResource.tuning().getValues().get("selectIds")); //Идентификатор отрытого объекта
	var comment = TunableObjectHelper.getAFInstanceValue(paramsResource.tuning().getValues().get("comment")); //Комментарий из кастомного диалога
	var version = TunableObjectHelper.getAFInstanceValue(paramsResource.tuning().getValues().get("versionContext")); //Версия открытого объекта

	var appdp = AFSession.get().getApplication(DPApplication.class);
	var obj = appdp.getEntityByUNID(ids.get(0));

	//Проверка на актуальность документа
	if (!isActualObject(ids.get(0), version)){
        process_dlgWarning(ids,"Данная версия объекта/документа была изменена. Требуется обновить документ!",returnResource);
		return returnResource.resource;
	}

	/*
	Алгоритм 
	*/	

	//Проверка при сохранении
	try {
	    obj.save();
	} catch (e) {
		process_dlgError(ids,"Произошел конфликт при сохранении документа. Требуется обновить документ!",returnResource);
		return returnResource.resource;
	}
}

Добавить кастомную кнопку и подключить кастомную операцию

  1. В форме создать секцию RootMenu
  2. В RootMenu создать button и подключить к нему handler



Информация
titleКоды иконок

https://conf.inttrust.ru:8443/pages/viewpage.action?pageId=59704445

Блок кода
languagexml
<section id="RootMenu">
    <component>
        <button name="${<Form Name>.RootMenu.button.<Name>:Новая кнопка}">
            <icon code="37"/>
            <action>
                <custom>
                    <operation>
                        <handler-ref ref="CustomHandlerName"/>
                    </operation>
                </custom>
            </action>
        </button>
    </component>
</section>