Есть деталь к разделу. В этой детали есть поле, связанное с этой деталью. В детали можно нажать кнопку изменить и откроется карточка редактирования. Можно нажать на подчеркнутое поле, ссылающееся на эту же таблицу, и откроется та же карточка редактирования, но для другой записи. Вопрос: как в скрипте этой карточки определить что карточка редактирования открыта для записи из реестра или для ссылки? Необходимо для того, чтобы некоторые поля в карточке разрешить/запретить для редактирования.
При открытии по кнопке или двойному клику по строке вызывается функция EditGridAreaData в scr_BaseGridAreaUtils. Если по ссылке, то DoLookupColumnClick в scr_WindowUtils, а из неё функция ShowDatasetEditWindow.
Далее в обоих случаях вызывается непосредственно функция показа карточки ShowEditWindowEx с одним из параметров Attributes, где хранятся атрибуты окна. Можно модифицировать вышеупомянутые функции, чтобы в атрибуты добавлялся свой, разный для открытия из реестра или по ссылке. А в карточке при открытии проверять его значение.
При изменении функций стоит учесть, что они используются во всех разделах, и не поломать существующую логику.
Александр, не хотелось бы править системные функции, потому что не зная тонкостей поломать логику очень легко. Поэтому и спросил, может есть готовые атрибуты окна при разных вызовах. А возможно ли в карточке при открытии сравнить ID активной записи реестра детали и ID переданного через атрибут в окно? Возможно ли установить между ними связь?
Александр, спасибо за подсказку. Немного проанализировав код я нашел у окна, вызываемого по ссылке, атрибут LookupColumnClick, который я и буду использовать.
Выдает ошибки:
И во-вторых, где взять ид, которые есть в скрипте
"entitySchemaUId", "C449D832-A4CC-4B01-B9D5-8A12C42A9F89"}
OpenTaskEditPage.PageUId = new Guid("F2BF397B-8FA3-48BA-B691-57360871967A");
По поводу ошибки "Имя OpenTaskEditPage отсутсвует в текущем контексте", в блоге указано (пункт 3), что после создания действия процесса "Открыть страницу", ему следует присвоить наименование. Вы либо не добавили UserTask, либо не так назвали.
А по поводу "UserContext" - какая у Вас версия, не 5.2 случаем?
PS:
ID в принципе вы можете не менять, т.к. это стандартные схемы(окна) и ID У Вас совпадут. А вообще, посмотреть их можно либо запросом в БД, либо в адресной строке, при открытии того или иного окна, указывается также и его идентификатор.
Да, действительно, я слишком поспешил, но по-моему там немного порядок нарушен.
Что касается версии, то 5.4.0.591
После всего остались две ошибки: "UserContext" и еще во втором скрипте (после сигнала IncidentEditPageClosed)
C "UserContext", т.е. с SessionData получилось.
На счет IncidentId. Она объявлена в первом скрипте, но второй скрипт идет как отдельная функция, т.е. она не видит что происходит в первом скрипте, соответственно не видит объявление IncidentId.
Или я что-то не понимаю? Как можно передать переменную из одного скрипта в другой?
Здесь, действительно, немного запутана очередность действий.
Логика следующая:
(сигнал нажатия на кнопку) -> (скрипт подготовки действия процесса "открыть карточку") -> (действие процесса открыть карточку) -> (сигнал закрытия карточки инцидента) -> (скрипт генерации номера инцидента).
И действительно - в последнем элементе набор данных "Инцидент" фильтруется по идентификатору только что созданной новой записи, и её присваивается определенный номер.
Т.к. для фильтрации используется переменная, скорее всего, нужно просто создать параметр страницы, и в первом скрипте, после генерации нового идентификатора, инициализировать этот параметр сгенерированным значением:
myParam = IncidentId;
А в последнем скрипте, вместо IncidentId использовать параметр.
Спасибо. Теперь подберусь немного к сути задачи. Мне надо создать именно инцидент (поставил id инцидента и его карточки, все нормально открывается). Что надо сделать, чтобы после нажатия на кнопку "Ок" у инцидента, т.е. инцидент создан в карточке e-mail он добавился в поле инцидент?
Александр, необходимо добавить сроку кода в элементе (скрипт генерации номера инцидента), т.е. в последний скриптовый элемент в рамках добавленной вами логики:
Но скрипт выполняется сразу после открытия окна инцидента, а т.к. запись еще не внесена он не видит эту строку, соответственно ничего не добавляет. Как подождать закрытия окна инцидента?
Коллеги, в тройке была возможность добавления действия на карточке редактирования любого объекта, с помощью которого можно было перейти к связанной сущности. То есть, например, на карточке задачи в поле редактирования контрагента можно было нажать на это действие (выглядело как молния) и из появившегося меню выбрать либо "Открыть карточку контрагента", либо "Перейти к контрагенту". Можно ли реализовать аналогичный функционал в BPMonline? Если да, то каким образом?
Также в тройке была возможность в реестре записей, например, тех же задач (и в других реестрах тоже) щелкнуть по почти любой колонке конкретной записи и открыть карточку редактирования этого объекта, например, щелкнув в реестре задач по контакту, открывалась карточка редактирования этого контакта. Возможно ли такое в BPMonline?
1) Посмотрите как реализовано тут http://www.community.terrasoft.ua/blogs/8319
2) В реестрах если нажать правой кнопкой мыши есть пункт - "Перейти к" - возможно этот функционал вам подойдет
Максим, по п.1, в целом, подходящая реализация, но громоздкая. кнопки занимают много места и не очень гармонично смотрятся на карточке. Особенно, если их создавать на многих полях. Может быть все же есть возможность реализации, аналогичной тройке? чтобы и места отъедать немного, и можно было бы заодно еще какое-то действие привязать, помимо открытия карточки.
по п.2: как вариант такая реализация вполне подойдет. Но "Перейти к" есть не во всех реестрах, а там где есть, переход предлагается только к одному полю (это либо Контрагент, либо Создал, либо Ответственный). Подскажите, как можно расширить этот список, а в тех реестрах где нет этого пункта, создать его?
Анна, спасибо за еще один вариант реализации. В принципе, он вполне хорош, за исключением того, что пользователю не очевидно, что произойдет по нажатию этой кнопки.
То, что можно пункты контекстного меню добавить по аналогии с существующими - хорошо. Но где можно посмотреть как это реализовано сейчас? в каком окне, в каком процессе, событии?
У нас обычная версия 5.2, неотраслевое решение. Сервис деска нет. В любом случае и в нашем решении есть стандартные меню "Перейти к Ответственному/Контрагенту и т.д.". Например, в разделе "Контрагенты" есть пункт "Перейти к -> Создал". Где можно посмотреть как это реализовано?
Пример создания контекстного меню можно посмотреть в базовом реестре (BaseGridPage), а конкретной реализации скрипта перехода - в процессе окна напоминаний (RemindingsPage) в обработчике JumpButtonClickScriptTask.
Анна, к сожалению, я так и не смог разобраться в BaseGridPage и повторить реализацию, например, меню "Отправить e-mail". Может быть, вы сможете описать подробнее что мне нужно сделать и какой код использовать?
Я добавил меню "Открыть" в общее контекстное меню в реестре контрагентов. Теперь я хотел бы, чтобы при наведении на этот пункт у меня открылись два пункта "Ответственный" и "Контакт". Соотв-но, меня интересуют все действия, которые мне нужно сделать, чтобы
1) при наведении на "Открыть" у меня появились два новых пункта
2) при нажатии на пункт меню "Ответственный" у меня открылась карточка редактирования ответственного за текущего контрагента сотрудника.
"D.T." написал:Также в тройке была возможность в реестре записей, например, тех же задач (и в других реестрах тоже) щелкнуть по почти любой колонке конкретной записи и открыть карточку редактирования этого объекта, например, щелкнув в реестре задач по контакту, открывалась карточка редактирования этого контакта. Возможно ли такое в BPMonline?
Это реализовывать отдельно не надо, переход к карточке любого поля-справочника автоматически формируется ядром, если поле вытянуто в реестр.
Если Вам необходимо добавить иерархический пункт меню в реестре, тогда при добавлении подпункта следует установить курсор на кнопку контекстного меню в дизайнере. из которой это подменю должно появляться. Обработчик нажатия писать отдельно.
"D.T." написал:То есть, например, на карточке задачи в поле редактирования контрагента можно было нажать на это действие (выглядело как молния) и из появившегося меню выбрать либо "Открыть карточку контрагента", либо "Перейти к контрагенту". Можно ли реализовать аналогичный функционал в BPMonline? Если да, то каким образом?
Для реализации это функциональности Вам следует в дизайнере карточки нажать правой кнопкой мыши на поле, и добавить на него кнопку-молнию, затем реализовать программный компонент перехода по аналогии с описанным тут: http://www.community.terrasoft.ua/blogs/8319
В новой для меня области начинают возникать различные вопросы...
Имеется задача: в разделе используется 5 типов например продуктов. Для двух из них нужно в карточке отобразить дополнительные пару полей.
Если пользоваться базовым функционалом, то мы создаем нужное количество карточек (в данном случае 5) для каждого типа, на основании одной базовой, содержащей все прочие поля. Далее в каждой карточке для каждого типа добавляем индивидуально дополнительные поля.
Далее в настройке Рабочих мест к разделу в деталь "Карточки редактирования" добавляем все 5 карточек для каждого типа отдельно. Все работает.
Нюанс. Мы не можем использовать две карточки - одна с допполями, другая без них, одна для нужных типов, другая для остальных, так как в этом случае получаем обрушение системы на моменте открытия раздела - в нем на кнопке "добавить" генерируются динамически пунктики для создания каждого из типов продукта с именем, включающим в себя id соответствующей страницы редактирования (ну а так как страниц всего две, а типов много - получаем два ActionMenuItem с одинаковы именем и крах...)
Вопрос. Для тонкой настройки множества параметров для разных типов эта схема удобна, а вот если все так, как я описал? Есть ли другой путь?
Кстати, вдогонку...
Гуру, подскажите для bpm-чайника стоит ли связываться и как проще сделать традиционное скрытие/показ контролов на карточке? Или такой метод будет идеологически совсем неправильным?
Александр, добро пожаловать в BPMonline :) На какой это версии? Думаю, стоит подправить базовую логику, чтобы название пункта меню формировалось как название типа + карточка.
Мы скрываем элементы управления используя метод public virtual void SetVisible(bool visible), он управляет видимостью с помощью выполнения скрипта на клиенте. и это быстрее, чем управлять видимостью меняя свойство public virtual bool Hidden, хотя так тоже можно.
Это версия 5.3.0.332
Базовая логика - с непривычки боязно, я буду бороться с этим страхом, обещаю;) настораживает, что это название потом может использоваться для подъема карточки, передаваясь куда-то. Соответственно править надо и его, почва для исследования есть.
А скрытие идеологически правильно будет, или все же надо стараться уходить от таких методов?
По-моему, не используется само название, там при создании реестра динамически формируются пункты выпадающего меню кнопки добавить в соответствии с зарегистрированной информацией в разделе Рабочие места и тут же им добавляются обработчики нажатия, так что не должно быть ничего преступного :)
В разумных пределах, думаю, это нормально, а если там 200 контролов скрыто, то может быть заметно.
У меня возник следующий вопрос, как можно узнать название карточки редактирования ? Предположим пользователь хочет изменить определенную карточку и показывает ее разработчику, как разработчику узнать название этой карточки, что-бы не перебирать все возможные варианты ?
Здравствуйте, Юрий
Рассмотрим пример (карточка счета в разделе счета)
Мы хотим найти сервис данной карточки в Terrasoft Administrator
Сервисы карточек редактирования, по договоренности в Terrasoft называют с окончанием Edit, к примеру
карточка контрагента - wnd_AccountEdit
карточка контакта - wnd_ContactEdit
Использовать поиск по заголовку
С точным поиском слова "Счет" после пару итераций мы дойдем до нужного нам сервиса wnd_InvoiceEdit.
Что бы перейти к следующему найденному совпадению слова, нужно нажать F3
Открыть сервис раздела, в нашем случае это - wnd_InvoicesWorkspace
и в коде соответствующему сервису раздела (scr_InvoiceWorkspace) посмотреть какое значение присваивается атрибуту EditWindowUSI
function InitializeGridData(){
...
SetAttribute(GridWindow, 'EditWindowUSI', 'wnd_InvoiceEdit');
...
}
Функция InitializeGridData вызывается в Initialize() - процесс инициализации раздела (Workspace), он вызывается на событии OnPrepare раздела
Все карточки редактирования заканчиваются на EditPage в названии. Заголовок же для карточки редактирования записи раздела начинается на "Страница карточки", для деталей и справочников на "Страница редактирования". Учтите также, что поиск по схемам BPMonline чувствителен к регистру.
Поправлю Сергея - названия страниц реестров имеют суффикс "GridPage" и множественное число сущности, пример: ContactsGridPage.
Если страницы создавали самостоятельно, то проще всего их найти путём отображения колонки с датой создания и сортировки по убыванию.
Добрый день! Скажите, пожалуйста, можно ли каким-то образом отражать во второй вкладке(или первой) окна редактирования карточки какую-либо закладку из этого же раздела. И при этом иметь возможность при этом удалять/добавлять записи на подобную закладку.
Здравствуйте Дарья.
Приведем пример, добавим в карточку редактирования wnd_IncidentEdit закладку описание и отобразим в ней содержимое детали [Описание]
Просьба ознакомится с прикрепленным файлом
Процесс создания закладки в карточке инцидента.doc
Добрый вечер!
Спасибо большое, но я имела ввиду немного другое.
В одной из презентаций я видела такой пример ( в прикрепленном файле)
Хотелось бы иметь возможность добавлять, удалять, изменять записи на этой закладке
Дарья, а можете показать как вы делали?
В вашем случае просто нужно при нажатии на любую из кнопок в реестре проверять в каком состоянии находится dataset карточки. Если состояние Insert, то автоматически делать сохранение. Но только в этом случае нужно сохранять где-то пометку о том, что карточка была автоматически сохранена. Потому что если пользователь нажмет кнопку Отмена -- нужно удалять созданную запись.
В карточке редактирования добавлено поле справочника и поле описаия значеия выбранного значения справочника. Но описание отображается только после сохранения данных в карточке. Как заставить отображать систему отображать поля связанного справочника после выбора нового значения в карточке редактирования?
Добрый день, Станислав!
Насколько мы поняли из предоставленного Вами описания проблемы: у Вас есть два поля, соответствующие двум связанным справочникам, в зависимости от выбранного значения в одном поле, значения другого варьируются и зависят от выбранного значения в первом справочнике.
Аналогичная функциональность реализована в карточке раздела "Задачи" (зависимость справочника "Результат" от справочника "Состояния"). Для реализации необходимой Вам функциональности Вы можете просмотреть реализацию стандартного функционала и сделать это по аналогии (сервис scr_TaskEdit). Для того, чтобы второй справочник открывался в карточке без пересохранения ее, Вам необходимо сперва объявить переменные, соответствующие ключам обоих справочников, а затем "наложить" фильтр. Как например, это реализовано в разделе задач:
function edtResultOnPrepareSelectWindow(LookupDataControl) {
var Dataset = dlData.Dataset;
var LookupDataset = LookupDataControl.DataField.LookupDataset;
var StatusID = Dataset.Values('StatusID');
var TaskTypeID = Dataset.Values('TypeID');
ApplyDatasetFilter(LookupDataset, 'TaskTypeID', TaskTypeID, true);
ApplyDatasetFilter(LookupDataset, 'StatusID', StatusID, true);
var AllowedResultIDs = GetAttribute(Self, 'AllowedResultIDs');
var IsResultIDsFilterEnabled = Assigned(AllowedResultIDs);
ApplyDatasetIncludeFilter(LookupDataset, 'IncludeID',
AllowedResultIDs, IsResultIDsFilterEnabled);
}
Нет. Немного не то. Есть в карточке задачи, например, поле "Контрагент" и есть поле, которое отображает, например, численность из карточки контрагента (отображение, недоступное для изменения. Поле "Численность" взято только для примера). Так вот численность отобразится в карточке задачи только после сохранения самой карточки, а при создании новой карточки при выборе контрагента у меня отображается пустое поле "Численность". Как мне отобразить значение? Нужен общий подход без привязки к конкретному полю. При этом может быть ситуация, когда мне нужно отобразить значение из справочника более глубокого вложения, т.е.: в задаче есть контрагент, у котрагента есть ссылка на id определенного справочника, из этого справочника нужно отобразить определенное поле.
Попробую объяснить на примере который Вы привели.
Нужно на событие изменения поля "Контрагент" датасета карточки задачи, делать запрос на получение значения поля "Численность" из датасета контрагентов.
Затем это значение присваивать контролу в котором нужно отобразить значение.
Можно использовать функцию GetDatasetFieldValueByID(DatasetUSI, ID, FieldName) из scr_DB.
Код будет выглядеть примерно следующим образом.
...................
function dlDataOnDatasetDataChange(DataField){if(!Assigned(DataField)){return;}
var DataFieldName = DataField.Name;
var Dataset = DataField.ParentDataFields.ParentDataset;switch(DataFieldName){case('AccountID'):
edtQuantity.Value= GetDatasetFieldValueByID('ds_Account', DataField.Value, 'Quantity');break;
...............................
В карточке редактирования wnd_...Edit предлагается выделять Caption визуальных контролов для полей Dataset-а с признаком "Только для чтения" цветом, отличающимся от цвета остальных полей, например, зеленым, или выставлять IsEnabled = false.
Если заголовки (Caption) визуальных контролов для полей с признаком "Только для чтения" и для других полей имеют один и тот же цвет, то пользователь постоянно путается при вводе данных.
Вот пример решения:
//Модуль scr_BaseDBEditUtils
function ProcessBaseDBEditOnPrepare(Window, BaseDBEdit){
...
/* Добавляем строчку в функцию... */
SetCaptionColorForIsReadOnlyFields(Window);//Устанавливает цвет для полей с признаком "Только чтение"}//Устанавливает цвет для полей с признаком "Только чтение"
function SetCaptionColorForIsReadOnlyFields(Window){for(var i =0; i < Window.ComponentCount; i++){if(!IsUndefined(Window.Components(i).DataField)){if(Window.Components(i).DataField.IsReadOnly){//Можно включить выделение цветом --> Window.Components(i).CaptionColor = clReadOnlyCaptionColor;
Window.Components(i).IsEnabled=false;}}}}
Добрый день, Петр.
В карточках редактирования элементы, поля которых имеют признак ReadOnly, отображаются серым цветом.
Если Вашим пользователям недостаточно базового отображения ReadOnly полей, то можно пойти и тем путем, который Вы описали. Действительно хороший вариант!