Коллеги, добрый день!

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

Данное уведомление появляется при попытке привязать данные на новом локальном стенде. Уже и перекомпилировал, и обновлял БД. Что это за объект администрирования?)
Скрин: https://yadi.sk/i/o6CEkWqU3GjtQA

Нравится

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

Проблема в следующем:
Здесь храниться дата изменения объекта
SELECT *
FROM [SysSchema]
WHERE UId = '84F44B9A-4BC3-4CBF-A1A8-CEC02C1C029C'

А здесь дата когда изменения были приняты
SELECT *
FROM [SysSchemaSource]
WHERE SysSchemaId = '1E9FA34C-B906-48E7-BC1A-241190FFBD6C'

Посмотрев на объекты, изменения были применены а вот с датами косяк.
Дата изменения в моей базе указана была: '2017-07-05 18:37:55.000'

Изменив дату последнего изменения на дату из таблицы SysSchemaSource у меня ошибка ушла
update SysSchema
SET ModifiedOn = '2017-04-04 11:31:40.877'
WHERE UId = '84F44B9A-4BC3-4CBF-A1A8-CEC02C1C029C'

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

Выполните операцияю [Обновить для требующих обновления]

"Терещук Павел" написал:Здравствуйте!

Выполните операцияю [Обновить для требующих обновления]

Павел, это первое, что пришло в голову - но нет, не помогает.

Найдите последний измененный [Объект администрирования]

Пересохраните, опубликуйте, после чего выполните операцию [Обновить для выбранных]

Объект администрирования - системный. К нему доступа нет.
добавьте sql сценарий и впишите в него запрос:

update SysSchema
SET ModifiedOn = (SELECT top 1 ModifiedOn
FROM [SysSchemaSource]
WHERE SysSchemaId = '1E9FA34C-B906-48E7-BC1A-241190FFBD6C')
WHERE UId = '84F44B9A-4BC3-4CBF-A1A8-CEC02C1C029C'

И собственно выполните затем сценарий

"Сурмачевский Евгений Александрович" написал:Объект администрирования - системный. К нему доступа нет.
добавьте sql сценарий и впишите в него запрос:

update SysSchema
SET ModifiedOn = (SELECT top 1 ModifiedOn
FROM [SysSchemaSource]
WHERE SysSchemaId = '1E9FA34C-B906-48E7-BC1A-241190FFBD6C')
WHERE UId = '84F44B9A-4BC3-4CBF-A1A8-CEC02C1C029C'

И собственно выполните затем сценарий

Евгений, спасибо помогло!

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

Нужна следующая функция в CRM: отправление ценового предложения клиенту
из CRM. или чтобы файл с ценовым предложением крепился к истории
клиента. В общем, чтобы информация о цене, которую менеджер дал клиенту,
сохранялась в CRM. Есть ли такая возможность? Версия 7.2.0.1184 bpmonline crm
Я так поняла, необходима доработка приложения, но что именно? Пожалуйста, помогите!

Нравится

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

Татьяна, добрый день!

Обе задачи требуют навыков программирования.

Для решения можно создать бизнес процесс. Логика процесса:
1) Создать активность с типом "Email". запись может быть создана элементом "Добавить данные". Обязательно нужно заполнить поля "Кому", "От кого", "Тема", "Тело"
2) Элементом "Задание-сценарий" необходимо:

  • Сформировать ценовое предложение. Для этого можно использовать методы из схемы ReportService
  • Заинсертить сформированный файл в таблицу ActivityFile, обязательно указав в поле ActivityId значение Id созданной на первом шаге активности
  • Отправить письмо

Не уверен, что в версии 7.2.0 есть пример такой отправки. Рекомендую зарегистрировать себе trial версию продукта service enterprise. В процессе "Отправка email сообщения контакту обращения" вы сможете найти пример кода.

3) Конец процесса

В случае с прикреплением ценового предложения к клиенту, можно пропустить первый пункт, поскольку активность не нужна. На втором пункте INSERT сформированного файла необходимо осуществлять в таблицу ContactFile/AccountFile (в зависимости от того контакт или контрагент является клиентом).

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

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

В объекты [Продукт в заказе] и [Продукт в счете] добавилось вычисляемое поле [Цена со скидкой]. Встала задача перенесения значения этого поля из продукта в заказе в продукт в счете при создании счета на основе заказа. Подскажите, пожалуйста, как это сделать? Заранее благодарю!

Нравится

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

Попробуйте с помощью бизнес процесса, который стартует по сигналу создания счета:
https://academy.terrasoft.ru/documents/technic-bpms/7-8-0/obzor-vozmozh…

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

перенос продуктов из Заказа в Счет происходит при выполнение бизнес-процесса "CreateInvoiceFromOrder". Если вы Дмитрий добавили новые вычисляемые поля в таблицы продуктов Заказа и Счета и вам требуется их переносить. Тогда мой совет скопировать бизнес-процесс "CreateInvoiceFromOrder" с новым названием и отредактировать элемент бизнес-процесса "Добавить продукты в счет", добавив свои новые созданные поля. После сохранить и опубликовать процесс. Далее вам требуется заместить страницу редактирования OrderPageV2 и добавить в Методы следующий замещающий код: (пример)

     /**
     * Запускает процесс создания счета по заказу.
     * @private
     */
     createInvoice: function() {
          ProcessModuleUtilities.executeProcess({
               sysProcessName: "NewCreateInvoiceFromOrder",
                    parameters: {
                                          CurrentOrder: this.get("Id")
                                     }
          });
     }

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

Благодарю, Михаил! Но данный способ подходит, если счет создается из действия "Создать счет на основании заказа". В нашем случае счет создается со вкладки "Паспорт заказа" с детали "График поставок и оплат": "+"-> 100% предоплата -> "Создать" счет на строке "Полная оплата товара". Как запустить процесс в этом случае?

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

"Дмитрий Д." написал:В нашем случае счет создается со вкладки "Паспорт заказа" с детали "График поставок и оплат": "+"-> 100% предоплата -> "Создать" счет на строке "Полная оплата товара". Как запустить процесс в этом случае?

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

Спасибо, Михаил! Действительно, рабочее решение, только вместо метода getInvoiceInsertQuery() правильнее переопределить getInvoiceProductInsertQuery(). Вот что у меня получилось в SupplyPaymentDetailV2:

getSupplyPaymentProductEntitySchemaQuery: function() {
	var esq = this.callParent(arguments);
 
	esq.addColumn("Product.UsrPriceWithDiscount", "UsrPriceWithDiscount");
	return esq;
},
 
getInvoiceProductInsertQuery: function(config, i) {
	var insert = this.callParent(arguments);
 
	var product = config.products.getByIndex(i);
	insert.setParameterValue("UsrPriceWithDiscount", product.get("UsrPriceWithDiscount"), this.Terrasoft.DataValueType.MONEY);	
	return insert;
}

Пожалуйста Дмитрий. Сейчас все получилось, что вы хотели? или еще остались вопросы?

Да, есть еще вопрос. При добавлении к заказу продукта у него автоматически рассчитывается [Сумма], [Сумма налога] и [Итого]. Мне нужно сюда же добавить логику расчета поля [Цена со скидкой]. Где я могу это сделать? Можно, конечно, в методе onEntityInitialized() карточки редактирования OrderProductPageV2, но мне кажется, что этим занимается какой-то бизнес-процесс.

"Дмитрий Д." написал:

Да, есть еще вопрос. При добавлении к заказу продукта у него автоматически рассчитывается [Сумма], [Сумма налога] и [Итого]. Мне нужно сюда же добавить логику расчета поля [Цена со скидкой]. Где я могу это сделать? Можно, конечно, в методе onEntityInitialized() карточки редактирования OrderProductPageV2, но мне кажется, что этим занимается какой-то бизнес-процесс.

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

Если я правильно вас понял Дмитрий, то речь идет об обновление полей Заказа, после добавления продукта в Заказ, весь расчет перечисленных вами полей происходит в бизнес-процессе схемы таблицы Продукты в заказе ("OrderProduct"), метод "RecalculateOrderAmount".

Если нужно пересчитывать поля в продукте заказа после сохранение заказа, то за это отвечает бизнес-процесс схемы таблицы Заказы метод "SetOrderProductCurrency"

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

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

"Дмитрий Д." написал:не совсем понятно, в какой схеме искать указанный вами метод?

Как выше написал Михаил, в схеме [OrderProduct].
Прикрепил скриншот для наглядности.

У нас в схеме [OrderProduct] нет такого метода, зато он есть в схеме [Order]. Каким образом возможно переопределить и дополнить этот метод в кастомном пакете?

Нужно просто заместить нужный Вам объект (в Вашем случае это [Order]). А уже в замещенном объекте можете переопределять этот метод в зависимости от своих потребностей. Если уже есть замещенный объект в пакете Custom, то просто открыть двойным кликом по методу и переопределить нужным Вам образом.

Давайте еще раз по порядку. Я переопределил схему [OrderProduct], открыл соответствующий ей процесс. Там есть методы UpdatePrimaryAmounts() и RecalculateOrderAmount() (как на скриншоте). Куда я могу вставить логику расчета кастомного поля объекта [OrderProduct], которая должна сработать при создании объекта (то есть при добавлении продукта в заказ)?

Дмитрий, кликаете два раза по методу (розовым цветом выделен на вашем скриншоте) и по центру открывается область с кодом этого метода. Или же справа в нижнем углу также есть аналогичный блок. Думаю, скриншоты крепить не нужно. В этих-то областях и можно писать свой код, вместо существующего.

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

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

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

Здравствуйте! Встала задача добавить для сущности Заказы вычисляемое поле, которое представляет собой разность полей Итого (Amount) и Суперкомиссия (UsrSuperFee). Создал такое поле по примеру из документации. Но так как это поле заполняется только в модели при выполнении метода onEntityInitialized() при загрузке карточки редактирования заказа, появляется кнопка "Сохранить" для сохранения этого значения в базу. Если же вынести вычисляемое поле в раздел Заказов, то там в этом поле будут, естественно, одни нули, потому что метод onEntityInitialized() здесь не выполняется.

Подскажите, пожалуйста, как правильно готовить вычисляемые поля? Не нажимать же на кнопку "Сохранить" на каждом заказе, чтобы заполнить его!

Нравится

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

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

по данной ссылки, что вы предоставили в своем обращение все правильно и верно описано как создать Вычисляемое поле. И в приведенном примере в документации Функция  this.calculateBalance исполняется в методе  onEntityInitialized для того чтобы при открытии карточки принудительно происходил расчет данного поля, что приведен в примере. Если вам этого не требуется выполнять а требуется чтобы расчет происходил, только к примеру при изменение какого-либо поля, то функцию  calculateBalance из метода  onEntityInitialized требуется исключить. И тогда при каждом открытии выполняться данная функция не будет. Или добавить условия при исполнение которого выполнялась бы данная функция.

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

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

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

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

Да, именно эту задачу мне требуется решить.

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

В [#Object#]SectionPageV2 нет метода onEntityInitialized(). По этой причине поле не считается, т.к. метод не вызывается.
В [#Object#]SectionPageV2 есть метод initData(), который Вы можете расширить для решения этой задачи.

"Демьяник Алексей" написал:В [#Object#]SectionPageV2 нет метода onEntityInitialized(). По этой причине поле не считается, т.к. метод не вызывается.

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

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

Алексей, не подскажете, как из initData() получить доступ к коллекции элементов заказов раздела, чтобы вставить логику расчета разности двух полей и поместить его в третье?

"Дмитрий Д." написал:Алексей, не подскажете, как из initData() получить доступ к коллекции элементов заказов раздела, чтобы вставить логику расчета разности двух полей и поместить его в третье?

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

при инициализации раздела и получение Потока Данных у вас не получится выполнить заполнение Вычисляемого поля. Для этого вам требуется создать отдельный бизнес-процесс который при срабатывание определенных условий на входе пересчитывал бы Одно данное поле в базе данных, а в разделе вы бы уже видели результат. Но и данный метод я бы сказал является ошибочным, так как если в Таблице будет Миллион записей, то на пересчет потребуется очень огромное количество времени и ресурсов. Это неверный подход. В опубликованной Вами ссылке Как добавить вычисляемое поле описан алгоритм создания вычисляемого поля для карточки редактирования. Рекомендую именно в карточки редактирования разместить данное вычисляемое поле. А в разделе еще раз повторюсь отображать только результат вычисления.

В дополнении к рекомендации заполнять данные в карточке, могу предложить для случаев, когда в карточке поле еще не рассчитано, но в реестре уже хочется видеть эту информацию:
1. Вывести в реестр данную физическую колонку, которую вы будете вычислять в карточке.
2. В схеме реестра, переопределить метод «addItemsToGridData», который срабатывает при загрузке порции данных в реестр. Т.к. реестр не отображает миллион строк, а только небольшими порциями (по 15 строк) удовлетворяющими фильтрацию, плюс при прокрутке вниз. Так же загружает все порциями, и в этот момент так же срабатывает метод «addItemsToGridData».
3. В методе для незаполненных строк, производить любые вычисления, и заполнять любые существующие колонки. (Важно: данные не уйдут в БД, а будут только информационными. В БД запись делайте при работе с карточкой.)
Пример переопределения метода, в котором я читаю и меняю поле Title строк. По аналогии можно читать и менять любое поле:

addItemsToGridData: function() {
   this.callParent(arguments);
 
   var gridDataItems = this.getGridData().getItems();
   gridDataItems.forEach(function(item) {
      var oldTitle = item.get("Title");
      item.set("Title", oldTitle + "!!!");
   }, this);
 
   console.log("new items loaded");
}

P.S. Так же думая об оптимизации при прокрутке реестра, не забудьте анализировать что поле уже заполнено к примеру так: if (item.get("Title")) { тут логика } что бы не выполнять лишние операции.
В моем случае это не имеет смысла, Title у меня и так всегда заполнен, и пример исключительно тестовый.

Еще немного оптимизации, анализ в методе только новой добавочной (15 строк) коллекции, зачем бегать по всему реестру, если там уже все рассчитано:

addItemsToGridData: function(dataCollection, options) {
	// forEach only new
	dataCollection.getItems().forEach(function(item) {
		var oldTitle = item.get("Title");
		item.set("Title", oldTitle + "!!!");
	}, this);
 
	this.callParent(arguments);
	console.log("new items loaded");
}

Спасибо Максим. Идея очень интересная. Попробую у себя так же протестировать. Только вот вопрос, что будет если колонка "Title" не будет добавлена в Реестр раздела. Ошибка будет или нет выдаваться. Попробую протестировать. Ведь пользователь любит добавлять и удалять преднастроенные колонки.

Максим, спасибо! Уже близко к истине. Только, насколько я понимаю, item в методе addItemsToGridData есть ViewModel, поэтому если какой-либо столбец не выводится в разделе, доступ к нему посредством метода item.get() невозможен. В этом случае нужно будет получать значения полей запросом к базе.

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

Благодарю.

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

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

как решить вашу задачу описал Илья Мотков в следующем инциденте. Последняя активность в реестре контрагентов посмотрите пожалуйста и по аналогии можно решить и вашу задачу.

Да, там всегда есть ID записи, по которой можно сделать esq, но в этом мало смысла, так как есть метод «initQueryColumns», который и определяет список загружаемых в модель колонок.
Можно заставить загружаться все колонки в модель, что несколько замедлит загрузку реестра:

initQueryColumns: function(esq) {
	this.callParent(arguments);
	this.addAllColumns(esq);
}

Либо по аналогии с реестром звонков, добавить только те колонки, что вам нужны:

initQueryColumns: function(entitySchemaQuery) {
   this.callParent(arguments);
   if (!entitySchemaQuery.columns.contains("IntegrationId")) {
      entitySchemaQuery.addColumn("IntegrationId");
   }
},

Разом изменить все существующие записи, можете либо бизнес процессом, либо SQL запросом.
В первом случае логику будете писать на C#, во втором на Transact-SQL.
Это если вы имеете в виду все-все существующие записи, а не только те, что выведены в реестр. И имеете в виду физические данные в базе данных, а не только информационно в реестре. Так как напоминаю, что в реестр данные грузятся порционно.

"Щиголь Максим" написал:Разом изменить все существующие записи, можете либо бизнес процессом, либо SQL запросом.
В первом случае логику будете писать на C#, во втором на Transact-SQL.

Я считаю что данную операцию лучше выполнять разово. Если создавать как постоянную бизнес-логику работы системы, то это может только привести к потере производительности, как я уже говорил выше всегда нужно помнить что рано или поздно количество записей в Таблице может достигнуть Миллиона записей и SQL серверу будет очень тяжело исполнять описанную бизне-логику.

Можете подсказать пример написания и выполнения SQL-скрипта в bpm'online 7.7? Что-то не нахожу подобного в документации.

Дмитрий опишите пожалуйста конкретные условия для получения выборки, я вам помогу составить SQL запрос

Собственно, необходимо для каждого Order вычесть из поля Amount поле UsrSuperFee и вставить результат в поле UsrAmountWithSuperFee.

"Дмитрий Д." написал:

Можете подсказать пример написания и выполнения SQL-скрипта в bpm'online 7.7? Что-то не нахожу подобного в документации.

Здравствуйте, Дмитрий!

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

"Дмитрий Д." написал:Собственно, необходимо для каждого Order вычесть из поля Amount поле UsrSuperFee и вставить результат в поле UsrAmountWithSuperFee.

вот Дмитрий сам запрос на обновление

update p set
p.UsrAmountWithSuperFee = p.Amount - p.UsrSuperFee
from Order as p

Спасибо, Алексей и Михаил, за помощь!
Я так решил: если нужно, чтобы вычисляемое поле объекта получало значение в зависимости от значений других полей, то сначала необходимо прогнать всю таблицу sql-запросом для заполнения вычисляемого поля, а уже в карточке редактирования объекта реализовывать логику пересчета его значения при необходимости.

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

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

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

Заранее спасибо!

Нравится

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

Здравствуйте, Дмитрий!

Такая возможность есть. Вам необходимо переопределить PrintReportUtilities, либо переопределить отдельные его методы на странице редактирования/в разделе нужного объекта.

Алексей, спасибо за ответ! Не могли бы вы привести пример? Или хотя бы ссылку на документацию по методам PrintReportUtilites?

Здравствуйте, Дмитрий!

Могу ответить точечно, но не по всему миксину:smile:

Рекомендую посмотреть тему http://www.community.terrasoft.ru/blogs/15581

Алексей, премного благодарен!

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

initSectionPrintForms: function(callback, scope) {
	var reportsEsq = this.getModulePrintFormsESQ();
	reportsEsq.filters.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
			"ShowInSection", true));
	reportsEsq.getEntityCollection(function(result) {
 
		if (result.success && !result.collection.isEmpty()) {
			// Коллекция пунктов меню
			var printFormsMenuCollection = result.collection;
 
			/* Тут можно анализировать свои «условия» и удалять те или иные элементы printFormsMenuCollection */
			printFormsMenuCollection.collection.items = printFormsMenuCollection.collection.items.sort(
				function(item1, item2) {
					if (item1.values.Caption > item2.values.Caption) {
						return 1;
					}
					if (item1.values.Caption < item2.values.Caption) {
						return -1;
					}
					return 0;
				});
 
			this.preparePrintFormsMenuCollection(printFormsMenuCollection);
			printFormsMenuCollection.each(function(item) {
				item.set("Click", {bindTo: "generateSectionPrintForm"});
			}, this);
			var printMenuItems = this.preparePrintButtonCollection(this.moduleSectionPrintFormsCollectionName);
			printMenuItems.loadAll(printFormsMenuCollection);
			this.set(this.moduleSectionPrintFormsCollectionName, printMenuItems);
			this.getSectionPrintButtonVisible();
		}
 
		if (callback) {
			callback.call(scope || this);
		}
	}, this);
}

Добрый день! Заметил баг при работе данного кода: если я перехожу в карточку Заказа из раздела, то список пунктов меню отображается без сортировки. Стоит мне обновить страницу, находясь в карточке, сортировка срабатывает. Причем код выполняется в обоих случаях, однако результат разный. В чем может быть проблема?

Здравствуйте, Дмитрий!

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

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

Здравствуйте, почему вы говорите о том, как ведет себя сортировка в карточке, и после обновления карточки. Если пишите метод «initSectionPrintForms». Так еще и речь заходит за написание этого кода в схеме секции.
Дело в том что, я было подумал что вы столкнулись с разницей работы кода в комбинированном режиме (когда слева видна часть секции, либо она спрятана за стрелочкой), и чистом режиме карточки (в который как раз можно попасть по F5).
Но метод initCardPrintForms, (CardPrint!) написанный в схеме страницы, отрабатывает как в комбинированном режиме, так и в чистом режиме карточки.
Вот к примеру чуть подправив ваш метод сортировки, написал его в initCardPrintForms, и в обоих режимах карточки, обратная сортировка работает:
Изначальный код метода брать необходимо из "PrintReportUtilities" т.к. от версии к версии он может разнится.

define("OpportunityPageV2", ["OpportunityPageV2Resources", "GeneralDetails", "StorageUtilities"],
function(resources, GeneralDetails, StorageUtilities) {
	return {
		entitySchemaName: "Opportunity",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
		]/**SCHEMA_DIFF*/,
		attributes: {},
		methods: {
			initCardPrintForms: function(callback, scope) {
				var reportsEsq = this.getModulePrintFormsESQ();
				var entitySchemaName = this.getEntitySchemaName();
				reportsEsq.filters.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
					"ShowInCard", true));
				StorageUtilities.GetESQResultByKey({
					esq: reportsEsq,
					key: "ShowInCard_PrintForm_" + entitySchemaName,
					callback: function(result) {
						if (this.destroyed) {
							return;
						}
						if (result.success && !result.collection.isEmpty()) {
							var printFormsMenuCollection = result.collection;
 
							printFormsMenuCollection.collection.items = printFormsMenuCollection.collection.items.sort(
								function(item1, item2) {
									if (item1.values.Caption > item2.values.Caption) {
										return -1;
									}
									if (item1.values.Caption < item2.values.Caption) {
										return 1;
									}
									return 0;
								}
							);
 
							this.preparePrintFormsMenuCollection(printFormsMenuCollection);
							printFormsMenuCollection.each(function(item) {
								item.set("Click", {bindTo: "generateCardPrintForm"});
							}, this);
							var printMenuItems = this.preparePrintButtonCollection(this.moduleCardPrintFormsCollectionName);
							printMenuItems.loadAll(printFormsMenuCollection);
							this.set(this.moduleCardPrintFormsCollectionName, printMenuItems);
							this.getCardPrintButtonVisible();
						}
						if (callback) {
							callback.call(scope || this);
						}
					},
					scope: this
				});
			}
		},
		rules: {},
		userCode: {}
	};
});

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

Максим, прошу прощения за двусмысленность. Я привел код initSectionPrintForms секции, но вел речь о методе initCardPrintForms.

Ваш код я попробовал, результат тот же. Может, причина в различиях версии продукта (у нас BMP'Online Sales 7.7.0.2293)?

Скажите, а где я могу посмотреть код PrintReportUtilities?

Как ни странно, но в схеме PrintReportUtilities. :smile:

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

Всем спасибо за помощь! Решил проблему добавлением логики сортировки нужной колонки при составлении запроса к базе, переопределив метод getModulePrintFormsESQ() в OrderPageV2:

/**
 * Возвращает клиентский запрос для получения печатных форм.
 */
getModulePrintFormsESQ: function() {
	var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
		rootSchema: SysModuleReport,
		isDistinct: true,
		rowViewModelClassName: "Terrasoft.BasePrintFormViewModel"
	});
	esq.addColumn(SysModuleReport.primaryColumnName);
	var captionColumn = esq.addColumn("Caption", "NonLocalizedCaption");
 
	// Устанавливает порядок сортировки колонки
	captionColumn.orderPosition = 0;
	captionColumn.orderDirection = Terrasoft.OrderDirection.ASC;
	...
	return esq;
}

То же самое сделал в методе getModulePrintFormsESQ() в OrderSectionV2 для раздела.

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

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

Заходите на сайт Terrasoft Academy и узнайте, как добавить рабочее место, раздел и деталь в мобильном приложении.

Видео доступно по ссылке: Мастер мобильного приложения.

Еще больше видео-уроков по настройке здесь.

Нравится

Поделиться

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

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

На примере практического кейса познакомитесь с процессом создания нового рабочего пространства.

Запись урока доступна по ссылке

Нравится

Поделиться

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

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

  1. Схемы пакета.
  2. Добавление схемы объекта.

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

Нравится

Поделиться

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

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

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

1. Установить в Web.config параметр IncludeDebugInformation в true и установить ему папку для сохранения схем:

2. Скомпилировать любую схему;

3. Войти в папку %TEMP%\BPMonline\TSBpm\Src

В папке будут файлы исходных кодов схем конфигурации, по которым можно произвести поиск любым файловым менеджером: TotalCommander, FAR Manager, Проводник Windows и т.д.

sourcecode

При компиляции конфигурации на сервере каждый раз собирается dll-библиотека, с которой затем работает ядро системы на сервере IIS.

Нравится

Поделиться

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

В поле "Искать файлы" лучше указать выражение "*.cs"

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

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

Нравится

Поделиться

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

Добрый день.
Сделал всё как в примере. По нажатии на кнопку ничего не происходит. С чем это может быть связано?

Вопрос снимается.

Анна, я попытался реализовать кнопку в карточке Задачи для перехода на страницу инцидента. Кнопка не работает.

Возможно это из-за этой строчки:

UserTaskOpenLead.PageUId = new Guid("df4b6147ca344ec998e5bd3a26c62b99");

Может для карточки инцидента существует другой Id?

Поменял на 280d4bf6689748e5a81e91bc6c501b3c - кнопка по прежнему неактивна.

Опять нарвался на ту же ошибку))
В материале следует исправить - кнопку нужно именовать не btnGotoLead, а просто GotoLead.

Как называть кнопку -- ваше дело, кстати, тут только фантазия ограничена только требованиями к идентификаторам. :smile:

Ну да не за этим пишу.
ИМХО, кнопку лучше добавлять прямо в поле, как на скриншоте. Так удобнее при выравнивании и пользователям понятнее... :smile:
А так все то же самое.

1

2

Не знаю. Уже несколько раз сталкивался - если именовать кнопку как в примере - ничего не работает.

Название кнопки и сообщение для обработчика в процессе должны соответствовать друг другу, например: MyCoolButton и тогда будет MyCoolButtonClick. А вообще оно автоматом генерится.
А также в скриптах скрытия/активации кнопки надо соответственно писать правильное название кнопки

Акмаль, убедитесь, что название обработчика кнопки в дизайнере страницы и название обработчика в стартовом событии совпадают.

Так ведь я о том и толкую. В примере они не совпадают.

Акмаль, благодарю за наблюдательность. Действительно, в примере нажатие кнопки генерирует событие btnGotoLeadClick, тогда как в обработчике отлавливается GotoLeadClick.

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

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