Здравствуйте!
Есть необходимость обновить деталь после изменения и добавления данных.

 details: {
                Proposition:{
                    schemaName: "PropositionDetailV2",
                    filter: {
                        masterColumn: "Id",
                        detailColumn: "ServiceInTransRequest"
                    },
                    subscriber: function (){
                        this.updateDetails();
                    }
                }
            },

Проблема заключается в следующем: при добавлении записи она отображается в гриде 2 раза (после обновления страницы все выводится верно). При изменении детали все хорошо.
Как избежать повторного отображения строки в гриде при добавлении новой записи, используя updateDetails()?

Нравится

32 комментария

Здравствуйте, Александр.

Деталь после добавления или изменения записи обновляется средствами базовой логики.
Попробуйте использовать код без функции subscriber

details: {
                Proposition:{
                    schemaName: "PropositionDetailV2",
                    filter: {
                        masterColumn: "Id",
                        detailColumn: "ServiceInTransRequest"
                    }/*,
                    subscriber: function (){
                        this.updateDetails();
                    }*/
                }
            },

функция Subscriber необходима, т.к. в детали реализована дополнительная логика и её нужно обновлять после любого изменения.
Деталь реализует предложения. По логике может быть только 1 исполнитель(булево поле). Если в какой-то записи уже выбран исполнитель, то в БД делается update. После этого мне необходимо обновить реестр детали в разделе.
Возможно ли как-то обновить значения в детали используя другие методы либо предотвратить дублирование записей при добавлении?

Здравствуйте, Александр.
Для корректного обновления детали и использования кода предоставленного Вами в обращении Вам необходимо обновить версию приложения до последней релизной версии 7.3.0.х которая имеет исправления касающиеся базовой логики обновления детали, получить которую Вы можете обратившись в техническую поддержку.

Добрый день. BPMOnline 7.4. Столкнулся с похожей проблемой. Для Детали реализована кнопка "Выбрать". Пользователь выбирает запись нажимает кнопку и запись обновляется. Для обновления детали(чтобы запись отображалась как выбранная) вызываю код
this.updateDetail(this.config);
В итоге в реестре детали отображаются две одинаковые записи. Одна старая, вторая обновленная. Может есть другой способ обновить деталь из кода самой детали?

Добрый день, Эмин!

Описанное Вами поведение детали может возникать по ряду причин:

1) Деталь некорректно размещена в контейнере. Можно посмотреть на diff детали и сравнить с другимим - на предмет правильной принадлежности её к Tab контейнеру, посмотреть на ParentName.
2) В config может передаваться некорректные значения, то есть старая деталь неправильно отображается.
3) Деталь загружается нестандартными методами, например не через diff, а в LoadDetailModule.

Эмин, в любом случае необходима отладка, думаю, что из всех перечисленных мной Выше пунктов - второй самый реалистичный.

Эмин, попробуйте так:

this.updateDetail(
      {
          detail: "MyDetailName",//название детали (как описана в карточке)
          reloadAll: true
      }
);

А в BPMonline 5.4 як оновити деталь в таких же умовах ?

Игорь, здравствуйте!
Подобная логика реализована в разделе «Контрагенты» на детали «Контакты» при добавлении нового контакта.
В методе ModifyAddPageParameters прописывается:
openPageParameters["CloseMessage"] = "ContactEditPageClosed";

В процессе детали реализована обработка сообщения ContactEditPageClosed с последующим выполнением скрипта:

public virtual bool ScriptContactEditPageClosedExecute(ProcessExecutingContext context) {
Page.TreeGrid.RefreshData();
return true;
}

Я вставку в журнал роблю в скрипті обробки події MeDeadUnblockRecord на BaseServiceRequestInBPMonlineEditPage.
В RecordAllChangesGridPage добавив у метод ModifyAddPageParameters рядок

openPageParameters["CloseMessage"] = "IncidentEditPageClosed";

і на повідомлення IncidentEditPageClosed створив обробника IncidentEditPageClosedScriptTaskExecute:

Page.TreeGrid.RefreshData();
return true;

По сигнальних записах у файл видно, що IncidentEditPageClosedScriptTaskExecute не відпрацьовує.

Игорь,
в данном случае Вам нужно генерировать сообщение из карточки на странице детали.
Необходимо передать идентификатор процесса детали ListenerPageProcessUId в страницу при загрузке. Если такой параметр процесса не существует – создать .
В процессе карточки BaseServiceRequestInBPMonlineEditPage реализовать вызов сообщения процесса детали RecordAllChangesGridPage в обработчике MeDeadUnblockRecord

if (string.IsNullOrEmpty(ListenerPageProcessUId)) {
return;
}
var process = UserConnection.ProcessEngine.FindProcessByUId(ListenerPageProcessUId);
if (process != null) {
process.ThrowEvent(process.InternalContext, “IncidentEditPageClosed”);
}

Добавив код:
RecordAllChangesGridPageEventsProcess.InitScriptTask3Execute:

UserConnection.SessionData["IncidentListenerPageProcessUId"] = ListenerPageProcessUId;

BaseServiceRequestInBPMonlineEditPage.MeDeadUnblockRecordScriptTaskExecute:

string listenerPageProcessUId = (string) UserConnection.SessionData["IncidentListenerPageProcessUId"];
 
if (!string.IsNullOrEmpty(listenerPageProcessUId))
{
	var process = UserConnection.ProcessEngine.FindProcessByUId(listenerPageProcessUId);
	if (process != null)
	{
		process.ThrowEvent(process.InternalContext, "ChangeLogIncidentEditPageClosed");
	}
}

Я замінив IncidentEditPageClosed на ChangeLogIncidentEditPageClosed, щоб не вийшло повторень.

ChangeLogIncidentEditPageClosedScriptTaskExecute:

Page.TreeGrid.RefreshData();

По сигнальних записах у файл видно, що ListenerPageProcessUId успішно проходить через усі скрипти, але ChangeLogIncidentEditPageClosed так і не спрацьовує.

Игорь,
В данной реализации необходимо записывать:
UserConnection.SessionData["IncidentListenerPageProcessUId"] = context.Process.UId;
Где context - параметр ScriptTask

Ну да, значення відрізняється.
В початковому варіанті поточне значення Guid доповнювалося кодом "PageContainer$IncidentsModulePage"

То яке ж має бути значення робочого ListenerPageProcessUId,
просто Guid,
чи
Guid + "PageContainer$IncidentsModulePage"
чи й взагалі
Guid + "PageContainer$RecordAllChangesGridPage" ?

Відразу відпишуся, що при використанні Guid означений код видає NULL:

UserConnection.ProcessEngine.FindProcessByUId(listenerPageProcessUId.ToString());

Власне й інші два варіанти також не дали бажаного ефекту.

Фантазія, тимчасово, вичерпалась :biggrin:

Игорь,
В случае БП следует применять первый вариант.
Для встроенных процессов карточек необходимо использовать
UserConnection.SessionData["IncidentListenerPageProcessUId"] = Page.Process.InstanceUId;

Так спрацювало.

Тепер виникло інше запитання.
При спробі отримати значення одного з об"єктів в скрипті ChangeLogIncidentEditPageClosedScriptTaskExecute:
Page.TreeGrid
Page.DataSource

виконання скрипта припиняється (видно по сигнальних записах у файл).

Схоже, що Page якийсь не такий.

Возможно, на момент EditPageClosed карточка начала закрываться и её компоненты уже недоступны.

Лучше логику вешать на нажатие кнопки «ОК», но до передачи сообщения в родительский процесс или на DataSourceSaved.

На кнопку "OK" спрацьовує стандартний алгоритм запису в журнал змін ("Изменение"),
а на "Отмена" та [x] має записуватися в журнал змін запис типу "Открытие".
З кнопкою "Отмена" простіше, а от на [x] доводиться включатися на рівні обробки "MeDeadUnblockRecord".

Та й, власне, на даний момент записи в журнал здійснюються, тільки після "OK" виконується автоматичне оновлення реєстру деталі журналу змін, а після "Отмена", [x] поки що ніяк не вдається заставити реєстр оновитися.

А можете показать весь скрипт ChangeLogIncidentEditPageClosedScriptTaskExecute?

Я пробував для нього два варіанти:

Page.TreeGrid.RefreshData();

і

var dataSource = Page.DataSource;
if (dataSource.Schema == null) {
	return true;
}
Page.TreeGrid.Clear();
dataSource.LoadRows();

Зараз думаю, що, можливо, краще з BaseServiceRequestInBPMonlineEditPage ініціалізувати подію для реєстра звернень. Як, наприклад, зміна активного звернення викликає оновлення реєстра журналу змін.

Попробуйте, но ведь BaseServiceRequestInBPMonlineEditPage — отдельное окно, а изменение активного обращения происходит в окне грида, встроенном в окно раздела.

BaseServiceRequestInBPMonlineEditPage окремим вікном є і для RecordAllChangesGridPage

Запитання в контекті використання об"єктів:
Page.TreeGrid
Page.DataSource

А Page може бути переданий в якості параметра, щоб потім ним скористатися ?

Опишу ще раз свою ситуацію:

В реєстрі звернень однією з деталей є журнал змін, який представлений "RecordAllChangesGridPage"

Якщо відкрити звернення і натиснути "[OK], то в журнал змін буде внесено запис "Изменение" і сам журнал на деталі буде оновлено.

Мені потрібно, щоб при натисненні "Отмена" чи [x] в журнал змін вносився запис "Открытие" і журнал на деталі так само оновлювався.

Я в обробник для "MeDeadUnblockRecord" вставив код, який створює запис "Открытие" в журналі.
Але після закриття вікна звернення (по [Отмена] чи [x]) журнал не оновлюється.

Отже задача: Заставити оновлюватися журнал на деталі в реєстрі звернень після закриття звернення по [Отмена] або [x]

Игорь, по результату телефонного разговора ждем от Вас описания поведения при применении блока try/catch в теле скрипта ChangeLogIncidentEditPageClosedScriptTaskExecute
Спасибо

Команда:
var treeGrid = Page.TreeGrid;

Повідомлення:
"Object reference not set to an instance of an object."

А це додатково, - зріз на момент початку роботи скрипта ChangeLogIncidentEditPageClosedScriptTaskExecute

Игорь, для дальнейшего анализа ситуации необходимо удаленное подключение. Написал персональное сообщение.

відповів у приват

Задача решилась путем добавления
В метод ModifyAddPageParameters:
openPageParameters["CloseMessage"] = "IncidentPageClosed";
В метод ModifyEditPageParameters:
openPageParameters["CloseMessage"] = "IncidentPageClosed";

Показать все комментарии