Дерево страниц
Skip to end of metadata
Go to start of metadata

Вы просматриваете старую версию данной страницы. Смотрите текущую версию.

Сравнить с текущим просмотр истории страницы

« Предыдущий Версия 6 Следующий »

Постановка задачи

Запустить процесс
Инструмент: Палитра XML
Статус

ГОТОВО

РазделWorkFlow
Комментарий

Реализация

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

Создать модель процесса

Создать модель процесса example_process (создание описано тут)

Загрузить модель процесса

Загрузка описана тут

Подключить WorkFlow-схемы в основную схему

Схема
<?xml version='1.0' encoding='UTF-8'?>
<schemas xmlns="http://www.intertrust.ru/schema/palette/tn-schema">
  <schema extends="RkkResource" name="RkkResourceInternal">
	<!--...-->
    <schema-ref name="wf" ref="WorkFlow"/>
    <schema-ref name="wfLifeCycle" ref="WorkFlowLifeCycle" null-empty="true" array="true"/>
	<!--...-->
  </schema>
</schemas>

Подключить жизненный цикл WorkFlow к форме

Форма
<?xml version='1.0' encoding='UTF-8'?>
<ui xmlns="http://www.intertrust.ru/schema/palette/tn-ui">
    <form schema-ref="RkkResourceInternal" id="RkkResourceInternalForm" name="${ui.form.RkkResourceInternalForm.name:}" projection="default" showtabs="true">
        <properties>
            <hide condition-union="AND">
                <negative-condition-ref ref="edit"/>
                <negative-condition-ref ref="read"/>
            </hide>
        </properties>
        <appearance widget="tabs"/>
        <component>
			 <!--...-->
             <section id="LifeCycle" name="${ui.form.RkkResourceInternalForm.section.LifeCycle.name:Жизненный цикл}">
                <properties>
                    <read-only condition-union="AND">
                        <condition>true</condition>
                    </read-only>
                </properties>
                <component>
                    <field attribute-ref="wfLifeCycle">
                        <properties>
                            <read-only condition-union="AND">
                                <condition>true</condition>
                            </read-only>
                        </properties>
                        <appearance location="table" importance="normal"/>
                    </field>
                </component>
            </section>
		 	<!--...-->
        </component>
    </form>
</ui>

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

Обработчик операций
<?xml version='1.0' encoding='UTF-8'?>
<ui xmlns="http://www.intertrust.ru/schema/palette/tn-ui">
    <handler name="WF-кнопка" id="WFCustomHandlerName">
        <meta>
            <documentation></documentation>
        </meta>
        <script lang="JavaScript"><![CDATA[код кнопки]]></script>
	</handler>
</ui>
Шаблон кода кнопки
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.af.tuning.impl.PropertyImpl);
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.ProcessVariables);
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);
importClass(Packages.org.slf4j.LoggerFactory);
importClass(Packages.ru.intertrust.cm.core.business.api.dto.Filter);
importClass(Packages.java.util.Collections);
importClass(Packages.ru.intertrust.cmj.af.so.SOApplication);
importClass(Packages.ru.intertrust.cmj.af.core.AFCMDomino);
importPackage(Packages.ru.intertrust.cm.core.business.api.dto.ReferenceValue);
importClass(Packages.ru.intertrust.cm.core.business.api.dto.StringValue);

function process(paramsResource, returnResource) {
	if (paramsResource == null) {
		throw new IllegalArgumentException("paramsResource must no be null.");
	}
	var paramPackageId = TunableObjectHelper.getAFInstanceValue(paramsResource.tuning().getValues().get("counter"));
	if (paramPackageId.equals("context")) { // обработка первого пакета данных
		process_context(paramsResource, returnResource);
	}
}


/**
 * Обработка первого пакета данных с клиента.
 * @param paramsResource
 * @return ресурс первого диалога сценария
 */
function process_context(paramsResource, returnResource) {
	var appTNObject = AFSession.get().getApplication(TunableObjectApplication.class);
	var ids = appTNObject.getClientContextIds(paramsResource.tuning());
	if (ids.isEmpty()) {
		throw new AFDaoBadParameterException("Не выбраны документы!");
	}

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

 	// Необходимо выдать исключение, если заявка удалена или прекращена в WD
    if ("Webdocs2.0".equals(AFSession.get().currentUser().extendedAttributes().get("ClientAlias"))) {
        var isTerminate = obj.tuning().getValues().get("wf") == null ? false : obj.tuning().getValues().get("wf").getValues().get("stage") == null ? false : obj.tuning().getValues().get("wf").getValues().get("stage").getValue().equals("Прекращена") ? true : false;
        if (obj.isDeleted() || isTerminate) {
            throw new RuntimeException("Заявка была удалена. Обратитесь к администратору")
        }
    }

	var workflowProcessService = BeansUtils.getBean("workflowProcessServiceImpl");

 	//запустить процесс
	var StartProcessResult = workflowProcessService.startProcess("example_process", ids.get(0), null);
	if (StartProcessResult.hasError()) {
		rollbackWF(appdp, ids.get(0), obj);
		throw new RuntimeException("Не удалось запустить процесс. Обратитесь к администратору");
	}

	//переоткрываем документ
	obj = appdp.getEntityByUNID(ids.get(0));

	//запись в Жизненный цикл
	var currentUser = AFSession.get().currentUser().getBeard();
	var executor = currentUser;
    var startDate = new AFDateTime(Calendar.getInstance());
	var endDate = new AFDateTime(Calendar.getInstance());
    var wf_status = "Отправка на исполнение";
    var stage = "На исполнение";
	var information = "-";

	setLifeCycle(obj, startDate, endDate, wf_status, executor, currentUser, stage, information);

	var time = new AFDateTime(Calendar.getInstance());
	TunableObjectHelper.putAFInstanceValue(obj.tuning(), "wf.actiontime", time);

	try {
	    obj.save();
	} catch (e) {
	    var appTNObject = AFSession.get().getApplication(TunableObjectApplication.class);
		var resultMessage = "При сохранении произошел конфликт, сохранение изменений невозможно.\nОбъект будет переоткрыт в актуальном состоянии."
		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");

        log.error("При сохранении произошел конфликт, сохранение изменений невозможно");

    	returnResource.resource = TunableObjectREST.Resource.create(message);
	    return returnResource.resource;
	}

	obj = appdp.getEntityByUNID(ids.get(0));
 	var res = RkkResource.valueOf(obj);
	returnResource.setResource(res);
}

/**
 * Откатить статусное состояние 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 = "";
	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();
		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("wfLifeCycle");
	var lifecycle = null;

	if (obj.tuning().getValues().containsKey("wfLifeCycle") && obj.tuning().getValues().get("wfLifeCycle") != 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("wfLifeCycle", lifecycleValue);
}


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

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


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



  • Нет меток