Здравствуйте.Очень хотелось бы получить возможность самостоятельно давать название, которое используется в коде для вкладок и групп полей. Также хотелось бы, чтобы мастер использовал какой-то единый стандарт для именования созданных разделов,деталей, вкладок, групп полей. От версии к версии продукта именование меняется и, к сожалению, не всегда в лучшую сторону. Например: 1. Не всегда используются ресурсы в карточках редактирования для свойства caption в diff. 2. Созданный раздел (и все относящиеся к нему схемы) в заголовке имеют название родительской схемы 3. К станицам деталей и самим схемам детали зачем-то приписывается 1. (UsrSchema1Detail, UsrAddIfro1Page) 4. Вкладки и группы полей именуются с добавлением id, хотя в одной из версий была возможность давать имя для вкладки. 5. В какой-то из версий можно было дать название вкладкам, в более поздних версиях данный функционал отсутствует. Прикреплю скриншет результата работы мастера раздела в версии 7.9

15 комментариев

Ой, еще некоторые схемы после работы Мастера начинаются с UsrUsr (зачем-то повторяется)

И добавлю сюда пожелание при создании страниц раздела для разных типов использовать наследование (с возможностью редактирования родительской страницы). Так как чаще всего все страницы Контрагентов, например, на 80% должны иметь общий наследуемые функционал, а не повторяться в странице каждого типа

"Владимир Соколов" написал:при создании страниц раздела для разных типов использовать наследование (с возможностью редактирования родительской страницы)

Поддерживаю, буквально недавно стояла такая задача, пришлось править таблицы в БД.

"Пащенко Александр Сергеевич" написал:пришлось править таблицы в БД

Мы без правок БД наследовали, но
1) много ручной работы
2) родительскую схему после этого получается редактировать только руками

Но плюсы перевешивают эти минусы!

Александр, здравствуйте!

Ниже обратная связь по Вашим замечаниям:

"Пащенко Александр Сергеевич" написал:
Очень хотелось бы получить возможность самостоятельно давать название, которое используется в коде для вкладок и групп полей.

Также хотелось бы, чтобы мастер использовал какой-то единый стандарт для именования созданных разделов,деталей, вкладок, групп полей.

Зафиксировали и передали информацию в департамент разработки для рассмотрения реализации в будущих версиях приложения.

"Пащенко Александр Сергеевич" написал:
1. Не всегда используются ресурсы в карточках редактирования для свойства caption в diff.

Если мы правильно поняли, то такая ситуация возможна если замещенная схема находится по иерархии выше родительского.

"Пащенко Александр Сергеевич" написал:
2. Созданный раздел (и все относящиеся к нему схемы) в заголовке имеют название родительской схемы

Зафиксировали и передали информацию в департамент разработки для рассмотрения реализации в будущих версиях.

"Пащенко Александр Сергеевич" написал:
3. К станицам деталей и самим схемам детали зачем-то приписывается 1. (UsrSchema1Detail, UsrAddIfro1Page)

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

"Пащенко Александр Сергеевич" написал:
4. Вкладки и группы полей именуются с добавлением id, хотя в одной из версий была возможность давать имя для вкладки.

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

5. В какой-то из версий можно было дать название вкладкам, в более поздних версиях данный функционал отсутствует.


[/quote]

Такая возможность есть на текущий момент в мастере раздела (рис. 1).

"Владимир Соколов" написал:

И добавлю сюда пожелание при создании страниц раздела для разных типов использовать наследование (с возможностью редактирования родительской страницы). Так как чаще всего все страницы Контрагентов, например, на 80% должны иметь общий наследуемые функционал, а не повторяться в странице каждого типа

Пожелание зафиксировали. К сожалению, при создании нескольких страниц редактирования, созданные страницы наследуются от BasePageV2.
Для решения твоей задачи:
1) Типизируй страницы редактирования раздела
Предположим при типизации раздела была создана страница с названием OldPage
2) Перейди в конфигурацию
3) Создай свою схему в конфигурации, назвав ее нужным именем (например MyPage)
4) Унаследуй ее от нужной страницы редактирования
5) Сохрани изменения
6) Выполни запрос:
update SysModuleEdit
set CardSchemaUId = (select Uid from SysSchema where name = MyPage and ExtendParent = 0)
where CardSchemaUId = (select Uid from SysSchema where name = OldPage and ExtendParent = 0)

"Владимир Соколов" написал:

Ой, еще некоторые схемы после работы Мастера начинаются с UsrUsr (зачем-то повторяется)

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

Дмитрий, спасибо за быструю обратную связь.
В третьем пункте также было замечание, что детали называются UsrSchema1Detail. (вне зависимости от того, как называется объект).

"Вильшанский Дмитрий" написал:5. В какой-то из версий можно было дать название вкладкам, в более поздних версиях данный функционал отсутствует.

Такая возможность есть на текущий момент в мастере раздела (рис. 1).

Здесь речь идет не о том, какой заголовок вкладки будет видеть пользователь в интерфейсе, а именно о том, как она будет называться в коде в секции diff (свойство Name).

"Пащенко Александр Сергеевич" написал:Здесь речь идет не о том, какой заголовок вкладки будет видеть пользователь в интерфейсе, а именно о том, как она будет называться в коде в секции diff (свойство Name).

Да, потом сложно в коде ориентироваться

Добавлю, что при включенном svn мастер самостоятельно не ставит замки на схемы.

"Пащенко Александр Сергеевич" написал:

Добавлю, что при включенном svn мастер самостоятельно не ставит замки на схемы.

Здравствуйте!

Отдел разработки работает над исправлением этой проблемы.

Добрый день. Вот еще новые "Фичи" работы мастера. Теперь если добавлять новое поле на страницу, то в названии у него никак не фигурирует название колонки, вместо этого написано, например "Float"+случайный Id.

Кроме того, все проблемы, которые описаны в данной теме все еще присутствуют, а уже прошло более года.

Александр, здравствуйте!

Улучшения находятся в работе, наши команды разработки постоянно улучшают наш продукт, с каждым новым релизом появляется все больше функционала и исправляются ошибки. Все реализованные доработки можно посмотреть здесь. Пожелания по наполнению схем мы все передаем, разработчики о них знают и, возможно, в последующих версиях ситуация улучшится.

Касательно замечания "Теперь если добавлять новое поле на страницу, то в названии у него никак не фигурирует название колонки, вместо этого написано, например "Float"+случайный Id.". Название колонки прописано в атрибуте "bindTo" в "values" поля. Данное поведение реализовано намеренно и скорее необходимо для того, чтоб если поля добавлять несколько раз в карточку, они в схеме были уникальными, и не было потом свалов в Мастере, например. Пожелание на доработку мы, конечно же, передали.

Одеяненко Юлия,

Безусловно, мастер стал более функциональным и удобным.

Ранее он брал название поля, а не его тип и добавлял к нему Id. Это было понятно. Сейчас же почему-то это изменили. Это влечет за собой дополнительную работу по исправлению названий для разработчиков, чтобы это хоть как-то было читаемо в дальнейшем. 

Аналогично с названием схем, созданных мастером деталей. Префикс в названии страницы дублируется дважды, детали называются по схема "Schema{0}Detail", их тоже приходится переименовывать.

В одной из версий системы, можно было давать название вкладкам, позже это убрали, хотя функционал был полезным.

 

Для пользователя, который не заходит в конфигурацию, никакой разницы нет, а для разработчика - это двойная работа, которая отнимает время.

Хотелось бы узнать предполагаемые сроки для данных правок и планируются ли они вообще?

Александр, здравствуйте!

К сожалению, точных сроков по реализации улучшению форматирования кода схем и названий схем, которые создаются Мастером, мы предоставить не можем. Проблем в данном посте озвучено достаточно много, они все находятся на рассмотрении у аналитиков продукта. Возможно, улучшения будут внедряться в будущих релизах, постепенно.

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

Здравствуйте подскажите пожалуйста каким образом можно заблокировать все элементы на карточке редактирования активности (поля, определенные кнопки, детали) т.е. что-бы пользователь мог посмотреть но не мог вносить изменения. Сделать это нужно именно кодом.! какой метод за это отвечает, ? т.е наверное при загрузке страницы есть какая то коллекция элементов , которую можно заблокировать?

Нравится

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

Добрый день Андрей!!!

я предлагаю вам ничего не кодировать, а выполнить вашу задачу путем разграничения прав "по колонкам". Для выполнения данной задачи прошу ознакомиться с документацией по Администрированию и настройки прав. Ссылка на Академию террасофт: Раздел [Доступ к объектам] Прошу обратить внимание "Администрирование по колонкам", "Администрирование по записям". именно данный метод вам подойдет для решения вашей задачи. Будут вопросы пишите.

Михаил спасибо за ответ, но так наверное, решить задачу не получиться, т.к поля должны блокироваться и разблокироваться по условию :
(поля должны быть заблокированы если с момента даты завершения Активности прошло более 10 дней и соответственно поля должны быть доступны если прошло менее 10 дней )

Тогда вам Андрей требуется доработка и переработка всей карточки редактирования. Но здесь возникает вопрос и определенная сложность. А если Задача (Активность) участвует в бизнес-процессе, тогда как вы будете использовать данную карточку? Ведь тогда Бизнес-процесс просто будет зависший. Это один момент. Второй момент во время исполнения Бизнес-процесса на карточки редактирования могут появляться Генерируемые поля. С ними что вы будите делать. Я думаю вы слишком замудреную поставили задачу. Ее решить можно но нужно будет предусмотреть все. А это переписать и заместить придется не только карточку редактирования Активности. Может вы как-то упростите задачу. И тогда я вам подскажу как правильно ее решить.

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

Намагаюся розібратися зі скриптом [PageLoadCompleteScriptTask].
В ньому використовуються значення полів, взяті наступним чином:

Page.ProductCategoryEdit.Value;
Page.HasAnalogsCheckBox.Checked;
Page.IsAdditionalHandlingRequiredCheckBox.Checked;
...

Значення отримую нульові, або інакше - в них ще не відобразилися значення з DataSource.
Якщо зчитати відповідні значення з DataSource, то все гаразд, є значення.
Але таке застосування не буде коректним.

Коли значення описаних полів ([Page...]) використовую у відповідному обробнику, що був описаний в [InitScriptTaskExecute], то на цьому етапі значення вже присутні.

Запитання: в який момент прописуються значення описаних полів ?
Куди потрібно прописувати логіку, яка спирається на вказані значення ?
Чи, що треба зробити, щоб поля гарантовано отримали свої значення ?

Нравится

10 комментариев

Игорь, здравствуйте!

"Ігор Андрусенко" написал:в який момент прописуються значення описаних полів ?

Значение интерфейсных полей изначально прописываются на клиентской части при помощи DataSource. Определение значений на сервере происходит, когда страница вернется с клиентской части.

"Ігор Андрусенко" написал:Куди потрібно прописувати логіку, яка спирається на вказані значення ?

Логику можно прописывать, например, на событиях изменений значений полей, на подготовку фильтров Lookup полей.
Не могли бы Вы описать логику применения значений полей и почему Вас не устраивает использование DataSource?
Спасибо

"y.perevjazko" написал:Не могли бы Вы описать логику применения значений полей и почему Вас не устраивает использование DataSource?

Мабуть справа в організації процесу оновлення полів.

На карточці заявки на внесення змін є пара полів типу дата.
Значення дат розраховуються в методі SetDeadlineDate().

Якщо метод запускається з якого-небудь обробника, то значення в полях фіксуються, в разі якщо обробник відпрацьовує.

А якщо метод запускається в скрипті PageLoadCompleteScriptTaskExecute,
то значення залишаються не зафіксованими.

Я так розумію, що обробник відпрацьовує по AJAX і дає миттєвий результат, а результат відпрацювання по скрипту фіксується після ситуативного надсилання даних на сервер.

Тому зараз запитання я б сформулював наступним чином:
Як заставити здійснити відправку даних на сервер не через обробник зміни значення якогось поля, а в примусовому порядку, у скрипті PageLoadCompleteScriptTaskExecute ?

Сделайте методу булевский параметр, на PageLoadComplete запускаете SetDeadlineDate(true), из других мест — SetDeadlineDate(false). Внутри метода в зависимости от параметра пишите или в поле датасорса (на PageLoadComplete), или в контрол на карточке.

Дещо "косим" способом запускаю метод:
вставив метод SetDeadlineDate() у скрипт обробки повідомлення SetTaskOwnerButtonClick (натиснення кнопки "Установить Content-менеджера").
При натисненні кнопки метод відпрацьовує, візуально значення змінюється.

Але далі отримав наступну мороку:
коли при першому натисненні кнопки вичитую його обома способами:

Page.DeadlineDateEdit.Value
Page.DataSource.ActiveRow.GetTypedColumnValue<DateTime>("DeadlineDate");

то отримую незмінене значення, не те, що в цей момент видно в полі карточки.
Вже коли вікно вибору менеджерів закриваю і потім повторно натискаю кнопку, тоді вичитується значення, яке було підставлене при попередньому натисненні-відпрацюванні SetDeadlineDate().

Це я вже з огляду на даний факт писав про AJAX.
Тому й питання щодо примусової відправки даних на сервер залишається актуальним, бо необхідність двічі розкривати вікно вибору Content-менеджерів навряд чи порадує виконавців.

Что это за окно выбора менеджеров? Оно открывается по кнопке? Как оно связано с полем?
Какой это продукт?

Так по кнопці відкривається вікно OwnerSelectionGridPage
З полем воно пов"язане таким чином:

UserConnection.SessionData["customDeadLine"] = Page.DeadlineDateEdit.Value;

Продукт: ServiceDesk
Я так розумію, що це додаткова розробка.

Але зважаючи на те, що при першому натисненні кнопки значення поля DeadlineDateEdit залишається неоновленим, то й у вікно передається неактуальне значення.
При другому - актуальне.

Возможно, проблема в том, что это поле некорректно заполнилось в другом месте на карточке, где ему присваивалось значение.

Рекомендуется всюду присваивать через

Page.DataSource.ActiveRow.SetColumnValue("DeadlineDate", DeadlineDate);

а не

Page.DeadlineDateEdit.Value = DeadlineDate;

Значення прописується ось так:

Page.DeadlineDateEdit.SetValue(deadlineDate);

Я так собі уявляю процес:
Значення прописується на боці клієнта, без відправки на сервер.
Тому не обновляється DataSource і, відповідно, зчитується не оновлене значення.
А при відкритті/закритті вікна по кнопці відбувається відправка даних, тому при наступному відпрацюванні SetDeadlineDate() показує, що значення вже оновлені.

А если заменить на Page.DataSource.ActiveRow.SetColumnValue ?

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

Добрый день!
Подскажите, пожалуйста, как для одного поля применить несколько правил отображения (в каждом правиле будет по несколько условий в массиве conditions). Т.к. если объявлено несколько правил отображения, то применяется только последнее правило.
И как реализовать правила отображения групп полей, Деталей и вкладок?

Нравится

10 комментариев

Здравствуйте, Игорь!
В таком случае, наверное лучше биндить параметр видимости на метод, который будет проводить необходимые вычисления и возвращать true или false. См. пример: http://www.community.terrasoft.ru/forum/topic/11983#comment-51919
У групп полей и деталей также есть свойство "visible".
Со вкладками сложнее - у них свойства "visible" нет, нужно либо добавлять css-свойство "display: none", либо динамически удалять/добавлять элементы коллекции "TabsCollection".

Нашел) только это 7.4.1

"Result": {
	"BindParameterEnabledResultToStatus": {
		"ruleType": BusinessRuleModule.enums.RuleType.BINDPARAMETER,
		"property": BusinessRuleModule.enums.Property.ENABLED,
		"conditions": [
			{
				"leftExpression": {
					"type": BusinessRuleModule.enums.ValueType.ATTRIBUTE,
					"attribute": "Status",
					"attributePath": "Finish"
				},
				"comparisonType": Terrasoft.ComparisonType.EQUAL,
				"rightExpression": {
					"type": BusinessRuleModule.enums.ValueType.CONSTANT,
					"value": true
				}
			}
		]
	},
	"BindParameterRequiredResultToStatus": {
		"ruleType": BusinessRuleModule.enums.RuleType.BINDPARAMETER,
		"property": BusinessRuleModule.enums.Property.REQUIRED,
		"logical": Terrasoft.LogicalOperatorType.AND,
		"conditions": [
			{
				"leftExpression": {
					"type": BusinessRuleModule.enums.ValueType.ATTRIBUTE,
					"attribute": "Status",
					"attributePath": "Finish"
				},
				"comparisonType": Terrasoft.ComparisonType.EQUAL,
				"rightExpression": {
					"type": BusinessRuleModule.enums.ValueType.CONSTANT,
					"value": true
				}
			},
			{
				"leftExpression": {
					"type": BusinessRuleModule.enums.ValueType.ATTRIBUTE,
					"attribute": "IsProcessMode"
				},
				"comparisonType": Terrasoft.ComparisonType.EQUAL,
				"rightExpression": {
					"type": BusinessRuleModule.enums.ValueType.CONSTANT,
					"value": true
				}
			}
		]
	}
}

чтобы правило работало на деталь или вкладку - вместо названия поля ("Result") пишите название детали

Спасибо, но в моём случае необходимы несколько
BusinessRuleModule.enums.Property.VISIBLE.
И к сожалению отрабатывает только последнее правило из массива.

так вы не несколько правил добавляйте, а несколько условий - как в правиле BindParameterRequiredResultToStatus

Я добавляю несколько правил BindParameterVisible, в которых в свою очередь в массиве conditions указываю по несколько условий.

вы добавляете несколько правил на одно свойство и ожидаете, что они как-то вместе будут работать?:exclaim: Даже если они как-то по очереди отработают, свойство-то одно и примет только одно, последнее значение

Вот это, к сожалению, и есть проблема, хотя при применении нескольких правил фильтрации поля, они вместе прекрасно отрабатывают. Придётся отказаться от использования rules и обратить свой взор на свойство visible. Спасибо за оказанное внимание

почему вы не можете сливать ваши несколько правил в одно с большим conditions?

Т.к. в каждом из правил есть по несколько condition'ов, объединённых
logical: Terrasoft.LogicalOperatorType.AND. Два параметра "logical" в одном правиле не применить. А в разных правилах присутствует условия, которые строятся на разных значениях одного поля + другое условие.

Единственное, что не пробовал - это передать в качестве элемента conditions массив условий.
Но думаю это ничего не даст.

да проще тогда методом)

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

Добрый день!

Возникла проблема: при скрытии поля (изменении свойства visible) образуется пустое место.
То есть расположенные ниже поля не занимают место скрытого поля.
Подскажите пожалуйста, как это исправить.

Использую платформу BPMonline 7.4 Для скрытия полей применяю правила (rules)

Заранее благодарен.

Нравится

6 комментариев

Добрый день, Дмитрий!
То, что Вы описали является ожидаемым и корректным поведением контрола. Скрытие полей никак не влияет на их расположение. Если пустое место вместо поля "режет глаз", можно попробовать передизайнить страницу таким образом, чтобы это поле находилось в самом низу, например.

А можно при скрытии как-то перемещать поля по сетке?
Скрыть, а нижние поднять програмно?

Нельза, т.к. расположение элементов в карточке задается статически

Да, "режет глаз" - это еще ладно. Просто, и так поля в bpm'online занимают много места на экране (зачастую нецелесообразно), а тут еще пустые места.

Надо в "Идеи" писать, наверное

Поддерживаю, разддражает, что остаётся пустое место, иногда "дырки" между полями.
Вот, допустим, мне поступило требование в зависимости от выбранного значения одного лукапа показывать либо то, либо иное поле, одно лукапное, другое текстовое, с одинаковым caption. Положил их рядом, когда одно из полей пропадает, образуется некрасивая "дырка".

Добрый день!

Огромное спасибо за пожелание к системе!
Мы обязательно его учтем для реализации в будущих версиях системы.

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

В процессе администрирования базы данных возникла необходимость определить причину возникновения ошибки. Определенный объём информации импортируется в базу данных, с которым далее пользователи работают. В процессе заполнения определенного набора полей автоматически высчитывалась итоговая сумма в поле «Итого». Но в определённый промежуток времени использования продукта начали появляться ошибки, связанные с несоответствием значения поля «Итого» сумме полей из которых оно вычисляется («Сумма покупки», «Наценка», «Сбор» и т.д.). Так как ошибку не получалось явно повторить, необходимо было разработать механизм для решения данной проблемы.

Естественно самой реальной и первой причиной возникновения такой ошибки приходила идея о сбоях в работе событий полей окна редактирования (то есть значения в полях изменялись, а события данных полей(-я) не срабатывали).

В основу решения было положено создание двух таблиц в базе данных для ведения логов, что происходят с записью набора данных. Первая таблица WindowLog, а вторая TriggerLog.

Первая таблица WindowLog включает в себя поля «Дата создания»(CreatedOn), «Идентификатор записи» (RecordID), «Ответственный» (WindowsUser), «Имя поля породившего событие»(FieldName), «Итого» и поля из которых оно вычисляется («Сумма покупки», «Наценка», «Сбор» и т.д.). Для наполнения таблицы было использованы события невизуального компонента окна dlData: dlDataOnDatasetDataChange, dlDataOnDatasetBeforePost и dlDataOnDatasetAfterPost. В скрипте в событиях была создана функция, которая формировала SQL запрос к таблице WindowLog базы данных с фиксацией информации по указанным полям на момент срабатывания события.

Запрос:

INSERT INTO WindowLog (*набор полей*)
SELECT (*набор полей*) -- Dataset('поле1'), Dataset('поле2'), Dataset('поле2')

Вторая таблица TriggerLog включает в себя поля «Дата создания»(CreatedOn), «Идентификатор записи» (RecordID), «Состояние» (до изменения записи и после), «SystemUser», «Итого» и поля из которых оно вычисляется («Сумма покупки», «Наценка», «Сбор» и т.д.). Для заполнения данной таблицы был создан триггер на инструкцию UPDATE проблемной таблицы с двумя запросами вставки значений в таблицу. В одном запросе вставлялись значения до изменений, а во втором после.

Запрос №1:

INSERT INTO TriggerLog (*набор полей*)       
SELECT (*набор полей*)
FROM deleted

Запрос №2:

INSERT INTO TriggerLog (*набор полей*)       
SELECT (*набор полей*)
FROM inserted

Результатом использования данного решения на основе анализа таблицы WindowLog было установлено, что срабатывают все события окна редактирования, влияющие на вычисление значения поля «Итого». В процессе использования окна редактирования и после сохранения записи значения поля «Итого» были корректны.

Проанализировав записи в таблице TriggerLog было установлено, что в результате выполнения инструкции UPDATE было внесено некорректное значение. Сопоставив даты создания записей в таблице TriggerLog и WindowLog было установлено, что инструкция UPDATE была вызвана не в результате манипуляций с окном редактирования, а иным источником. На основании поля «SystemUser» таблицы TriggerLog было установлено что изменения были внесены с помощью импортера данных.

Таблицу TriggerLog возможно расширить, добавив в нее поля, которые помогут ускорить процесс обнаружение источника изменений записи базы данных. Список дополнительных полей может выгладять следующим образом: ApplicationName, LoginName, HostName.

PS: Принимаю предложения на доработку вашей конфигурации!!! Для более детальной информации можно связаться по следующему e-mail адресу: providnui@ukr.net !!!

В случае возникновения дополнительных вопрос по теме могу поделиться более детальной информацией.

Всем удачи в этом не легком процессе!!!

Нравится

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

Здравствуйте! Прошу помощи. Я новичок в CRM и у меня возникла проблема в создании функционала. Дело вот в чем: Есть стандартная карточка редактирования "Задачи". Я изменил её, сделав некоторые поля не доступными в зависимости от типа задачи, вот функция:

function SetTaskTypePrepare() {
var Account = Self.ComponentsByName('edtAccount');
var Contact = Self.ComponentsByName('edtContact');
var Opportunity = Self.ComponentsByName('edtOpportunity');
var Invoice = Self.ComponentsByName('edtInvoice');
var Document = Self.ComponentsByName('edtDocument');
var Contract = Self.ComponentsByName('edtContract');
var Report = Self.ComponentsByName('frmReport');
var PercentDue = Self.ComponentsByName('edtPercentDue');
var ActualStartDate = Self.ComponentsByName('edtActualStartDate');
var ActualFinishDate = Self.ComponentsByName('edtActualFinishDate');
var ActualDurationStr = Self.ComponentsByName('edtActualDurationStr');
var FrameGroup9 = Self.ComponentsByName('FrameGroup9');
var Author = Self.ComponentsByName('edtAuthor');
var Result = Self.ComponentsByName('edtResult');
var DetailedResult = Self.ComponentsByName('mmDetailedResult');
var StatusID1 = '{F598ECDB-4EEF-4FA8-9E69-A36B053501E5}';
var TypeID = '{CED7CC70-81CB-4AB1-A9F2-521998B14723}';
var TypeIDMeeting = '{63FB4E89-EE75-404F-8352-1E712AC909F6}';
if ((dlData.Dataset.Values('TypeID') == TypeID) || (dlData.Dataset.Values('TypeID') == TypeIDMeeting)) {
Account.IsEnabled = false;
Contact.IsEnabled = false;
Opportunity.IsEnabled = false;
Invoice.IsEnabled = false;
Document.IsEnabled = false;
Contract.IsEnabled = false;
PercentDue.IsEnabled = false;
ActualStartDate.IsEnabled = false;
ActualFinishDate.IsEnabled = false;
ActualDurationStr.IsEnabled = false;
FrameGroup9.IsEnabled = false;
Author.IsEnabled = false;
Report.IsEnabled = true;
Result.IsEnabled = true;
DetailedResult.IsEnabled = true;
} else {
Account.IsEnabled = true;
Contact.IsEnabled = true;
Opportunity.IsEnabled = true;
Invoice.IsEnabled = true;
Document.IsEnabled = true;
Contract.IsEnabled = true;
PercentDue.IsEnabled = true;
ActualStartDate.IsEnabled = true;
ActualFinishDate.IsEnabled = true;
ActualDurationStr.IsEnabled = true;
FrameGroup9.IsEnabled = true;
Author.IsEnabled = true;
Report.IsEnabled = false;
if (dlData.Dataset.Values('StatusID') == StatusID1) {
Result.IsEnabled = true;
DetailedResult.IsEnabled = true;
} else {
Result.IsEnabled = false;
DetailedResult.IsEnabled = false;
}
}
}

Эта функция вызывается в событии OnPrepare окна редактирования. Работает все отлично, если вызывать окно редактирования стандартной кнопкой "Добавить" под гридом. Но стоит задача, сделать вызов этого окна редактирования из другого раздела (Квартиры - новый раздел). Вот, что я сделал:

function CreateTaskCall() {
var EditWindowUSI = 'wnd_TaskEdit';
var TypeID = '{CED7CC70-81CB-4AB1-A9F2-521998B14723}';
var Attributes = GetNewDictionary();
Attributes.Add('NotifyObject', Self);
var DefaultValues = GetNewDictionary();
var PriorityID = '{F6E5132C-BFC4-48E4-832B-0A60BBF6FC57}';
var StatusID = '{F598ECDB-4EEF-4FA8-9E69-A36B053501E5}';
var DwellingID = '{1E1C4BCB-6730-492A-BB38-4E5A4035EAE4}';
var GenderID = '{4D1769C4-7AB2-4F1A-A227-B0C922412A7C}';
var RoomsID = '{B1837FB0-6B28-4021-A1B7-4DFE0EC6CBAF}';
var FormPaymentID = '{F304FD41-2637-4F30-A4C1-DBD0D6F5BE51}';
/*DATE MODULE*/
var DateWithTime = GetLocalDateTime();//new Date().getTime();
DateWithTime = DateWithTime + 270000;
var DT = new Date(DateWithTime);
DateWithTime = DT.getVarDate(DateWithTime);
DefaultValues.Add('TypeID', TypeID);
DefaultValues.Add('PriorityID', PriorityID);
DefaultValues.Add('StatusID', StatusID);
DefaultValues.Add('DwellingID', DwellingID);
DefaultValues.Add('GenderID', GenderID);
DefaultValues.Add('RoomsID', RoomsID);
DefaultValues.Add('FormPaymentID', FormPaymentID);
DefaultValues.Add('DueDate', DateWithTime);
ShowEditWindowEx(EditWindowUSI, Attributes, DefaultValues);

Эта функция вызывается кликом по нужной строке в меню действия из раздела Квартиры.

Проблема: При открытии окна из меню раздела Квартиры, поля "Результат" (edtResult) и "Результат подробно" (mmDetailedResult) остаются недоступными (по задумке их должен редактировать пользователь), хотя если открыть эту карту стандартной кнопкой "Добавить", то все работает нормально. Прикладываю скрины.

Нравится

1 комментарий

Разобрался, ошибка была в функции TaskEditOnPrepare, просто строки надо было поменять местами :lol:

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

1. Откройте сервис карточки окна редактирования контрагента wnd_AccountEdit;
2. Выберите поле, Которое планируется скрывать в зависимости от типа, и скопируйте его название:

01

По имени поля мы будем обращаться к нему из скрипта, меняя свойство IsEnabled:

edtField.IsEnabled = true;

3. Откройте запрос справочника Тип контрагента sq_AccountType.
Нажмите просмотр запроса

02

Затем выполнить запрос:

03

В окне Результаты мы получим список идентификаторов, по которым мы будем проверять.

Например, если на нужно показывать поле только для типа Партнер, программный код будет выглядеть следующим образом:

if (Dataset('AccountTypeID') ==  '{2229B3B7-9210-4B3A-AAAD-2A4168678CA1}'){
edtField.IsEnabled = true;
edtField.IsVisible = true;
}else{
edtField.IsEnabled = false;
edtField.IsVisible = false;
}

4. Вставлять данный программный код нужно в двух местах:
- на открытие карточки
- на изменение значения поля Тип

Откройте скрипт карточки редактирования контрагента scr_AccountEdit и найдите функцию function wnd_AccountEditOnPrepare(Window)

04

В конец функции вставьте следующий программный код:

               if (dlData.Dataset('AccountTypeID') ==  '{2229B3B7-9210-4B3A-AAAD-2A4168678CA1}'){
                               edtField.IsEnabled = true;
                               edtField.IsVisible = true;
               }else{
                               edtField.IsEnabled = false;
                               edtField.IsVisible = false;
               }

06

Найдите функцию function dlDataOnDatasetDataChange(DataField) и добавьте в нее следующий программный код:

               if(FieldName == 'AccountTypeID'){
                               if (Dataset('AccountTypeID') ==  '{2229B3B7-9210-4B3A-AAAD-2A4168678CA1}'){
                                               edtField.IsEnabled = true;
                                               edtField.IsVisible = true;
                               }else{
                                               edtField.IsEnabled = false;
                                               edtField.IsVisible = false;
                               }
               }

07

5. Сохраните и закройте скрипт. Перезапустите Terrasoft.

В результате поле Отрасль будет отображаться только для контрагентов с типом Партнер.

Нравится

Поделиться

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

GUID хорошо выносить в константы (scr_Consts).

Кроме IsVisible и IsEnabled может понадобиться edtField.DataField.IsRequired.

Согласен с Александром и для повышения читабельности кода использовать конструкцию типа:

...
edtField.IsVisible = Dataset('AccountTypeID') == '{222...8CA1}';
edtField.IsEnabled = Dataset('AccountTypeID') == '{222...8CA1}';
...

+1 к предыдущему, но ещё я в декоративных целях добавляю скобки:

edtField.IsVisible = (Dataset('AccountTypeID') == '{222...8CA1}');

Это повышает читаемость, особенно в сложных условиях:

edtField.IsVisible = (Dataset('AccountTypeID') == '{222...8CA1}') || (Dataset('AccountTypeID') == '{333...8CB2}')

Коллеги, благодарю!
В случае, если значений много, действительно гораздо функциональнее будет такая конструкция :)

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

Добрый день коллеги!

Не могу реализовать переход фокуса по полям в форме стрелками вверх, вниз, вправо,влево.

код обработчика события onKeyDown примерно такой:

function edtEditionsOnKeyDown(Control, Key, Shift) {
switch (Key.Value) {
case VK_UP:

Self.FocusedControl = edtText;
break;
case VK_DOWN:

Self.FocusedControl = edtText1;
break;
}
}

Внутрь события проваливается , но фокус не перемещается ни при каком раскладе.

Если любыми другими клавишами (ентер, бекспейс,ф1, ф2) то фокус нормально перемещается
как решить?

Нравится

1 комментарий

Здравствуйте
Воспользуйтесь событием OnKeyUp, стрелки вверх и вниз передают фокус передается контролам.

function edtTest2OnKeyUp(Control, Key, Shift) {
if (Key.Value == 40)
{
MessageBox(Key.Value);
 
Self.FocusedControl =  edtTest1;
}
else
{
MessageBox(Key.Value);
Self.FocusedControl =  NumericEdit;
}
Показать все комментарии

Только начинаю работать с системой. Разбираюсь с разработкой печатных форм. Встал вопрос, как понять в какой таблице и в каком поле хранятся нужные мне данные? Смотрел руководства, SDK. Нигде не нашел.

Нравится

10 комментариев

Здравствуйте, Вениамин.

К сожалению, на текущий момент нет руководства с описанием структуры базы данных и таблиц Terrasoft. Но, если у Вас возникнут конкретные вопросы, где хранятся те или иные данные, мы, в рамках технической поддержки, обязательно Вам подскажем.

Инна Безверхняя,
II линия службы поддержки Terrasoft

Здесь просто нужно понимать общую структуру расположения сервисов в дереве в администраторе, это поможет находить нужную вам информацию.
Обычно в верхней иерархии идут разделы (названия на английском):

По названиям разделов вы можете определить где находятся нужные вам таблицы в зависиомости от того, к какому разделу они относятся.
Далее идут подгруппы:

- Detail
Здесь хранятся все сервисы, связанные с деталями раздела
- Dictionaries
Здесь хранятся все сервисы, связанные со справочниками раздела
- General
Здесь находятся сервисы, которые отвечают за отображения основного реестра записей раздела
- Graphs - графики
- Library - библиотека специфичных для этого раздела сервисов
- Reports - различные сервисы, связанные с отчетами FastReport
- User Fields - сервисы, связанные с пользовательскими полями

После того, как вы нашли сервис нужной вам таблицы, открываете этот сервис и слева вы увидите список полей таблицы:

Я могу в чем-то ошибаться, но общее представление у меня такое.

Андрей, огромноее спасибо. Действительно, все более-менее понятно.

Здравствуйте, Андрей!
Спасибо за Ваш ответ, да, в целом все верно.

Вениамин, хотелось бы еще добавить, что помимо того, что структура сервисов в TS Admin довольно однотипна для всех разделов, структура таблиц в самой БД также довольно прозрачна и, если можно так сказать, интуитивно понятна.

То есть, для каждого раздела есть основная таблица, на примере раздела "Контрагенты" - tbl_Account, далее, вся связанная информация, которая заносится через детали этого раздела хранится в таблицах, которые начинаются с названия раздела + название детали, то есть tbl_AccountAddressess - адреса контрагентов, tbl_AccountCommunications - средства связи контрагентов и т.д., аналогично справочная информация по данному разделу tbl_AccountType - типы контрагентов и т.д.
По тому же принципу хранится информация о группах записей и правах доступа к записям: tbl_AccountGroup и tbl_AccountRight.

По такому принципу хранится информация из всех разделов со всеми соответствующими связями.
Ну и, конечно, служебные таблицы, такие как, например, tbl_DatabaseInfo, в которой Вы можете посмотреть информацию о версии базы, кешировании сервисов и прочее.

Это в общих чертах, подробнее будем рады ответить на более конкретные вопросы.

Инна Безверхняя,
II линия службы поддержки Terrasoft

Инна, отличное дополнение! Картинка постепенно прорисовывается. Спасибо :)

Вениамин, для более углубленного анализа (уже для этапа программирования конфигурации) могу порекоммендовать SDK, в котором Вы сможете найти описание свойств и методов для используемых в системе интерфейсов.

А вот по какому принципу хранится информация в табличке tbl_Service ? Особенно блоб "XMLData".
В каком виде хранятся тексты "сервисов" ? Ну точно не в виде чистого XML.

Здравствуйте Сергей,
При записи в таблицу tbl_Service, сам сарвис сериализируется, подробнее вы можете почитать в теме http://www.community.terrasoft.ru/forum/topic/6829

"Яворский Алексей" написал:
При записи в таблицу tbl_Service, сам сарвис сериализируется, подробнее вы можете почитать в теме http://www.community.terrasoft.ru/forum/topic/6829

Насколько я понял из приведённого топика - XML-сериализация производится при выгрузке сервиса (модуля) в текстовый файл. При загрузке - XML-десериализация. А вот на стадии записи в БД выполняется маршалинг (сохранение всего объекта, включая программу, данные и метаданные). Попросту вся область памяти объекта (сервиса) выгружается в BLOB. Или я ошибаюсь?

Вопрос простой - как просмотреть/отредактировать модуль (сервис) во внешнем приложении имея доступ к БД? IBExpert воспринимает обсуждаемый BLOB как двоичный (это естественно при неизвестной структуре).

Здравствуйте Сергей,

Для редактирование сервиса из БД необходимо:
1.Получить значение BLOB-поля
2.Разархировать его – получится XML сервиса
3.Редактировать текст XML
4.Заархивировать
5.Записать заархивированный XML в то же поле

Но редактирование XML на прямую может повлечь ошибки. Если сервис неправильно отредактирован и записан в БД, он станет недоступным для редактирования в TSAdmin и для использования в TSClient, т.к. он не сможет правильно дисериализироваться.

Для решения Вашей задачи лучше работать с сервисами через COM-объекты Terrasoft из любого внешнего приложения:
1.Например, запросить сервис sq_Contact (Services.GetNewItemByUSI)
2.Модифицировать его как угодно, добавлять колонки, фильтры, union’ы и т.д. – это минимизирует ошибки, т.к. COM-объекты Terraosft делают проверку возможности тех или иных изменений. А работа напрямую с текстом XML ничего не проверяет
3.И после модификаций сохранить Services.SaveItem(Service, sdoaSave) в БД

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