Чтобы получить список элементов именно диаграммы БП, а не экземпляра (т.е. не содержимое tbl_WorkflowItem, а содержимое сервиса диаграммы БП):
надо:
1. добавить в окно LookupControl с DatasetLink'ом на датасет mds_WorkflowDiagramAction
2. для этого контрола добавить обработчик OnPrepareSelectWindow:
var Dataset = LookupControl.LookupDatasetLink.Dataset;
var DiagramUSI = GetAttribute(Self, 'DiagramUSI');
SetAttribute(Dataset, 'DiagramUSI', DiagramUSI);
}
где DiagramUSI - USI диаграммы БП (я брал из атрибутов)
3. В скрипте mds_WorkflowDiagramActionScript изменить:
var Designer = Dataset.Attributes('Designer');
var Diagram = Designer.ServiceCopy;
var DiagramItem;
на
var Designer = Dataset.Attributes('Designer');
if (!Assigned(Designer)) {
DiagramUSI = Dataset.Attributes('DiagramUSI');
if (!IsEmptyValue(DiagramUSI)) {
var Diagram = Services.GetNewItemByUSI(DiagramUSI);
} else return;
} else {
var Diagram = Designer.ServiceCopy;
}
var DiagramItem;
кстати, это я сделал для функционала перезапуска привязанных бизнес-процессов для записей:

вроде бы отрабатывает, хотя функционал все-таки админский
если кому-нибудь интересно - напишу попозже
Дмитрий, напишите, пожалуйста, для каких задач используется приведенный вами функционал, чтобы было понятнее.
"Кошкаров Андрей" написал:Дмитрий, напишите, пожалуйста, для каких задач используется приведенный вами функционал, чтобы было понятнее.
В разделе записи создаются исключительно по БП.
Но БП переделывается, глючит и т.д. В таких ситуациях возникает необходимость, не удаляя запись, перезапустить БП.
Я дал себе такую возможность :biggrin:. А приведенный функционал использую для выбора элемента (шага) БП, с которого надо начать заново. Т.е. я выбираю ActionItem, который станет активным после перезапуска.
"Андросов Дмитрий" написал:вроде бы отрабатывает, хотя функционал все-таки админский
если кому-нибудь интересно - напишу попозже
Дмитрий, Вы можете полный вариант своего решения опубликовать, нам как раз такой функционал нужен по перезапуску БП с данного элемента.
На гриде раздела лидов, которые создаются только по БП, есть кнопка:

на нее повешена следующая логика:
[javascript]
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();
}
[/javascript]
окно выглядит так:
![]()
обратите внимание: для выбора элемена БП используется базовый mds_WorkflowDiagramAction, в котором (как указано в шапке) надо изменить:
[javascript]
function FillDatasetFromDiagramDesigner(Dataset) {
var Designer = Dataset.Attributes('Designer');
if (!Assigned(Designer)) { // это
DiagramUSI = Dataset.Attributes('DiagramUSI'); // это
if (!IsEmptyValue(DiagramUSI)) { // это
var Diagram = Services.GetNewItemByUSI(DiagramUSI); // это
} else return; // это
} else { // это
var Diagram = Designer.ServiceCopy;
} // это
var DiagramItem;
[/javascript]
скрипт для окна:
[javascript]
//-----------------------------------------------------------------------------
// 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;
}
[/javascript]
получив оповещение на гриде отрабатывает:
[javascript]
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);
}
[/javascript]
[javascript]
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();
}
}
}
[/javascript]

[javascript]
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;
}
[/javascript]
cq_ClearBaseOfWorkflowItemIDs
[sql]
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 = -1 break
if @@fetch_status = -2 continue
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
[/sql]
не претендую на изящность, делалось по пути и кусками))
в любом случае оно проще, чем кажется