Подскажите, пожалуйста, верно ли будет сказать, что после срабатывания данного БП запись из раздела "Контакты" с ИИН равным "000000000011" будет видеть только консультант и системные администраторы?
Для условного потока элемента «Выполнить задачу» в конструкторе бизнес-процессов, доступен следующий вариант результатов условного потока (см. рисунок), данное отображение работало до версии 7.8 для нашего пользовательского элемента «Действие процесса» разработанного на основе элемента «Выполнить задачу», можно ли как-нибудь сделать такое же отображение для текущей версии BPM?
Ответ:
Для того, чтобы реализовать функционал на подобии элемента "Выполнить задачу" для пользовательского элемента, рекомендуется ознакомиться с реализацией в исходном коде элемента "ActivityUserTask" (метод GetResultParameterAllValues).
Чтобы получить список элементов именно диаграммы БП, а не экземпляра (т.е. не содержимое tbl_WorkflowItem, а содержимое сервиса диаграммы БП):
надо:
1. добавить в окно LookupControl с DatasetLink'ом на датасет mds_WorkflowDiagramAction
2. для этого контрола добавить обработчик OnPrepareSelectWindow:
function edtWFItemNameLUOnPrepareSelectWindow(LookupControl, SelectWindow){ var Dataset = LookupControl.LookupDatasetLink.Dataset; var DiagramUSI = GetAttribute(Self,'DiagramUSI');
SetAttribute(Dataset,'DiagramUSI', DiagramUSI); }
где DiagramUSI - USI диаграммы БП (я брал из атрибутов)
3. В скрипте mds_WorkflowDiagramActionScript изменить:
function FillDatasetFromDiagramDesigner(Dataset){ var Designer = Dataset.Attributes('Designer'); var Diagram = Designer.ServiceCopy; var DiagramItem;
на
function FillDatasetFromDiagramDesigner(Dataset){ var Designer = Dataset.Attributes('Designer'); if(!Assigned(Designer)){
DiagramUSI = Dataset.Attributes('DiagramUSI'); if(!IsEmptyValue(DiagramUSI)){ var Diagram = Services.GetNewItemByUSI(DiagramUSI); }elsereturn; }else{ var Diagram = Designer.ServiceCopy; } var DiagramItem;
"Кошкаров Андрей" написал:Дмитрий, напишите, пожалуйста, для каких задач используется приведенный вами функционал, чтобы было понятнее.
В разделе записи создаются исключительно по БП.
Но БП переделывается, глючит и т.д. В таких ситуациях возникает необходимость, не удаляя запись, перезапустить БП.
Я дал себе такую возможность :biggrin:. А приведенный функционал использую для выбора элемента (шага) БП, с которого надо начать заново. Т.е. я выбираю ActionItem, который станет активным после перезапуска.
На гриде раздела лидов, которые создаются только по БП, есть кнопка:
на нее повешена следующая логика:
function amiRestartSelectedLeadsOnExecute(ActionMenuItem, Sender){// перезапускает БП для выбранных записей
var SelectedIDs = ListToArray(grdData.SelectedIDs);if(SelectedIDs.length){RestartLeadsBP(SelectedIDs);}}
function amiRestartAllLeadsOnExecute(ActionMenuItem, Sender){// перезапускает БП для всех отфильтрованных записей
var Dataset = dlData.Dataset;
var SelectedIDs =[]
Dataset.GoToFirst();while(!Dataset.IsEOF){
SelectedIDs.push(Dataset('ID'));
Dataset.GoToNext();}if(SelectedIDs.length){RestartLeadsBP(SelectedIDs);}}
function RestartLeadsBP(SelectedIDs){// SelectedIDs - массив
var WorkflowItemNameWindow = Services.GetNewItemByUSI('wnd_EnterRestartWorkflowItemName');
SetAttribute(WorkflowItemNameWindow, 'NotifyObject', Self);
SetAttribute(WorkflowItemNameWindow, 'SelectedIDs', SelectedIDs);// получаем USI диаграммы, к которой принадлжит привязанный к записи элемент БП
var DiagramUSI = GetDatasetFieldValueByID('ds_WorkflowItem',
GetDatasetFieldValueByID('ds_Leads', SelectedIDs[0], 'WorkflowItemID'),
'DiagramUSI');
SetAttribute(WorkflowItemNameWindow, 'DiagramUSI', DiagramUSI);
открываем окно выбора параметров перезапуска
WorkflowItemNameWindow.Show();}
окно выглядит так:
обратите внимание: для выбора элемена БП используется базовый mds_WorkflowDiagramAction, в котором (как указано в шапке) надо изменить:
function FillDatasetFromDiagramDesigner(Dataset){
var Designer = Dataset.Attributes('Designer');if(!Assigned(Designer)){// это
DiagramUSI = Dataset.Attributes('DiagramUSI');// этоif(!IsEmptyValue(DiagramUSI)){// это
var Diagram = Services.GetNewItemByUSI(DiagramUSI);// это}elsereturn;// это}else{// это
var Diagram = Designer.ServiceCopy;}// это
var DiagramItem;
скрипт для окна:
//-----------------------------------------------------------------------------// wnd_EnterRestartWorkflowItemNameScript//-----------------------------------------------------------------------------
var Data ={};
function wnd_EnterRestartWorkflowItemNameOnClose(Window){
btnCancelOnClick();}
function btnOKOnClick(Control){
Data.MppContactID= edtOwner.Value;
SendNotify(Self, MSG_OK, Data);// посылаем Notify обратно на окно грида (где и отрабатывается логика рестарта)
Self.Close();}
function btnCancelOnClick(Control){
SendNotify(Self, MSG_CANCEL);// посылаем Notify обратно на окно грида (где и отрабатывается логика рестарта)
Self.Close();}
function edtWFItemNameLUOnPrepareSelectWindow(LookupControl, SelectWindow){
var Dataset = LookupControl.LookupDatasetLink.Dataset;
SetAttribute(Dataset, 'DiagramUSI', GetAttribute(Self, 'DiagramUSI'));}
function edtWFItemNameLUOnChange(LookupControl){
var Dataset = LookupControl.LookupDatasetLink.Dataset;
Data.WFItemName= Dataset('Name');// сохраняем имя выбранного элемента БП}
function wnd_EnterRestartWorkflowItemNameOnPrepare(Window){
edtWFItemNameLU.Value= null;
edtWFItemNameLU.Text= null;}
получив оповещение на гриде отрабатывает:
function wnd_LeadsGridAreaOnNotify(ScriptableService, Sender, Message, Data){
var Dataset = dlData.Dataset;if(Message == MSG_OK){if(Sender.Caption=='wnd_EnterRestartWorkflowItemName'){
var SelectedIDs = GetAttribute(Sender, 'SelectedIDs');//Data.SelectedIDs; if(!!SelectedIDs.length){// здесь немного логике по обработке выбранного нового ответственного (для записи лида)
var WorkflowItemName = Data.WFItemName;
var MppContactID = Data.MppContactID;
var MppContactIDs =[];
var UpdateOwner =true;if(!IsEmptyGUID(MppContactID)){for(var i =0; i < SelectedIDs.length; i++){
MppContactIDs[i]= MppContactID;}}else{for(var i =0; i < SelectedIDs.length; i++){
MppContactIDs[i]= GetDatasetFieldValueByID('ds_Leads', SelectedIDs[i], 'OwnerID');// если не выбрано - берется из текущего датасета
UpdateOwner =false;}}
ProcessRestartLeadsBP(SelectedIDs, WorkflowItemName, MppContactIDs, UpdateOwner);// сама функция}
var RecordID ='';for(var i =0; i < SelectedIDs.length; i++){
RecordID = SelectedIDs[i];
RecreateDefaultRights(['tbl_Leads'], 'OwnerID', null, true, RecordID);// немаловажно, если поменяли ответственного - обновляем права на запись (функционал см здесь - _http://www.community.terrasoft.ru/blogs/9611#comment-40937)
Dataset.RefreshRecord(RecordID, true);}return;}}
wnd_BaseGridAreaOnNotify(ScriptableService, Sender, Message, Data);}
function ProcessRestartLeadsBP(SelectedIDs, WorkflowItemName, MppContactIDs, UpdateOwner){// функция-обертка
RestartWorkflowBySelectedRecordsInTableAndWorkflowItemName('tbl_Leads', SelectedIDs
, WorkflowItemName, MppContactIDs, UpdateOwner);}
function RestartWorkflowBySelectedRecordsInTableAndWorkflowItemName(TableName // название таблицы записей, на основе которых делается перезапуск
, SelectedIDs // массив ИД записей
, WorkflowItemName // название элемента, на который перезапустится БП
, MppContactIDs // массив новых ответственных для записей (согласованный с массивом SelectedIDs )
, UpdateOwner){// признак, что надо обновлять ответственного
var CQ = GetSingleItemByCode('cq_ClearBaseOfWorkflowItemIDs');// см ниже - много sql// по сути: зачищаем все ссылки на конкретный экземпляр БП (связанный с конкретной записью) во всех (опционально) таблицах и в этой самой записи
CQ.Parameters.ItemsByName('BaseTableName').Value= TableName;
CQ.Parameters.ItemsByName('IncludedString').Value= SelectedIDs.join();
CQ.Parameters.ItemsByName('Delimeter').Value=',';
CQ.Parameters.ItemsByName('AllTables').Value=true;
CQ.Execute();
var WorkflowEngine = GetWorkflowEngine();
var Now =new Date(System.Now()).getVarDate();
var Dataset = GetSingleItemByCode('ds_Leads', 'RestartWF');if(Assigned(WorkflowEngine)&&!IsEmptyGUID(WorkflowItemName)){// не знаю почему IsEmptyGUID, наверно я имел ввиду IsEmptyValue ))for(var i =0; i < SelectedIDs.length; i++){// запускаем новый экземпляр БП, с параметром IsFake = true (который провоцирует остановку в самом начале - см. элемент "Задержка" (см. скрин ниже)
var WF_ID = WFStartByUSI('wd_LeadsMain'
,['LeadsID', 'MppContactID', 'IsFake']
,[SelectedIDs[i], MppContactIDs[i], true]);// принудительно запускаем БП с нужного нам элемента (с нужными нам параметрами)
var WorkflowItemWF_ID = StartWorkflowItem(WF_ID, WorkflowItemName
,['LeadsID', 'MppContactID', 'IsFake']
,[SelectedIDs[i], MppContactIDs[i], false]);// и обновляем WorkflowItemID для выбранной записи
ApplyDatasetFilter(Dataset, 'ID', SelectedIDs[i], true);
Dataset.Open();
Dataset.Edit();if(!!UpdateOwner){
Dataset('OwnerID')= MppContactIDs[i];}
Dataset('WorkflowItemID')=!IsEmptyGUID(WorkflowItemWF_ID)? WorkflowItemWF_ID : null;
Dataset.Post();
Dataset.Close();}}}
function WFStartByUSI(WorkflowUSI, ParamNames, ParamValues){
var WorkflowEngine = GetWorkflowEngine();
var Now =new Date(System.Now()).getVarDate();
var Params = WFArrayToParams(ParamNames, ParamValues);
var ID;/*if (!!NoReturn) {
if (Assigned(Params)) {
WorkflowEngine.StartWorkflow(WorkflowUSI, Now, Params);
} else {
WorkflowEngine.StartWorkflow(WorkflowUSI, Now);
}
return;
}*/if(Assigned(Params)){
ID = WorkflowEngine.StartWorkflow(WorkflowUSI, Now, Params);}else{
ID = WorkflowEngine.StartWorkflow(WorkflowUSI, Now);}return ID;}
function StartWorkflowItem(WorkflowID, ItemName, ParamNames, ParamValues){
var WorkflowEngine = GetWorkflowEngine();
var Now =new Date(System.Now()).getVarDate();
var Params = WFArrayToParams(ParamNames, ParamValues);
var ID;if(Assigned(Params)){
ID = WorkflowEngine.StartWorkflowItem(WorkflowID, ItemName, Now, Params);}else{
ID = WorkflowEngine.StartWorkflowItem(WorkflowID, ItemName, Now);}return ID;}
cq_ClearBaseOfWorkflowItemIDs
declare @BaseTableName varchar(250)=:BaseTableName
declare @TableName varchar(250)=:TableName
declare @IncludedString nvarchar(4000)=:IncludedString
declare @delimeter1 nvarchar(4000)=:Delimeter
declare @AllTables int=:AllTables -- опция для обработки всех таблиц с полем WorkflowItemID
if(@AllTables =1)
begin -- получаем список всех таблиц с полем WorkflowItemID
declare tc cursor local fast_forward for
select name from SYSOBJECTS where
ID in (SELECT id FROM SYSCOLUMNS WHERE NAME='WorkflowItemID')and xtype ='U'and name != @BaseTableName
open tc
end
else
begin -- либо берем из параметра
declare tc cursor local fast_forward for
select name from (values (@TableName)) as X(name)
open tc
end
while(1=1)
begin
fetch next from tc into @TableName
if @@fetch_status =-1breakif @@fetch_status =-2continue
print @IncludedString
print @TableName
exec(N'
-- для парсинга IncludedTablesString start
-- см _http://www.community.terrasoft.ru/blogs/10130
declare @input_str nvarchar(4000) = '''+ @IncludedString +'''
declare @IncludedTablesStringTable table (Code uniqueidentifier)
declare @IncludedTablesStringCode nvarchar(4000)
declare @delimeter nvarchar(4000) = '''+@delimeter1+'''
declare @pos int = 0
declare @len int = LEN(@input_str + cast(2 as varchar)) - 1
declare @lend int = LEN(@delimeter + cast(2 as varchar)) - 1
declare @oldpos int = 0
declare @substr nvarchar(4000)
while (@pos <= @len)
begin
set @substr = SUBSTRING(@input_str, @pos, @lend)
if (@substr = @delimeter or @pos = @len)
begin
set @substr = SUBSTRING(@input_str, @oldpos,
@pos - @oldpos + case when (@pos = @len) then 1 else 0 end
)
insert into @IncludedTablesStringTable (Code) values (@substr)
set @pos = @pos + @lend
set @oldpos = @pos
continue
end
set @pos = @pos + 1
end
-- для парсинга IncludedTablesString end
-- собственно логика зачистки ссылок на БП
update '+ @TableName +' set WorkflowItemID = null
where WorkflowItemID in (select ID from tbl_WorkflowItem where WorkflowID in
(select WorkflowID from tbl_WorkflowItem where ID in
(select WorkflowItemID from '+ @BaseTableName +' where ID in
(select Code from @IncludedTablesStringTable)
)
)
)
update '+ @BaseTableName +' set WorkflowItemID = null
where ID in
(select Code from @IncludedTablesStringTable)
')
end
close tc
deallocate tc
Предлагаю ввести новые элементы - карточка поиска (тут можно обойтись созданием нового типа схемы представления) и карточку вида. Второй вариант - карточка с настраиваемыми в БП полями, для заполнения данными разных объектов, то есть можно будет создать карточку, не привязанную ни к одному объекту, но данными которой можно будет заполнить сразу несколько не связанных объектов.
Предлагаю ввести новые элементы - карточка поиска (тут можно обойтись созданием нового типа схемы представления) и карточку вида. Второй вариант - карточка с настраиваемыми в БП полями, для заполнения данными разных объектов, то есть можно будет создать карточку, не привязанную ни к одному объекту, но данными которой можно будет заполнить сразу несколько не связанных объектов.
"Салихов А" написал:Второй вариант - карточка с настраиваемыми в БП полями, для заполнения данными разных объектов, то есть можно будет создать карточку, не привязанную ни к одному объекту, но данными которой можно будет заполнить сразу несколько не связанных объектов.
В 7.0.1 есть действия «Автогенерируемая страница» и «Преднастроенная страница». Первая — список полей настраивается в свойствах действия. Вторая — страница создаётся обычным образом, но не привязанная к объекту в БД, данные передаются через параметры.